美文网首页
自定义button 可设置圆角 边框 按下颜色

自定义button 可设置圆角 边框 按下颜色

作者: 好多个胖子 | 来源:发表于2017-07-06 14:13 被阅读3952次

一、为什么要自定义这样的Button

在Android开发中,按钮是最经常使用的控件,按钮所涉及的样式无非几种

  1. 边框
  2. 圆角
  3. 按下的颜色
example.png

现在有一个按钮的需求如下:

1.背景颜色: 正常: #ff0000  按下: #008888
2.文字颜色:正常: #ffffff  按下: #000000
3.圆角:弧度为5dp
4.边框:宽度:2px  颜色:#000000

1. selector+shape

  • 编写背景selector+shape
//正常shape   normal.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <corners android:radius="5dp" />
    <stroke
        android:width="2px"
        android:color="#000000" />
    <solid android:color="#ff0000" />
</shape>

//按下shape  press.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">

    <corners android:radius="10dp" />
    <stroke
        android:width="2px"
        android:color="#000000" />
    <solid android:color="#008888" />
</shape>


//selector
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:drawable="@drawable/normal" android:state_pressed="false" />
    <item android:drawable="@drawable/press" android:state_pressed="true" />
</selector>

  • 编写文字颜色selector
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="#ffffff" android:state_pressed="false" />
    <item android:color="#000000" android:state_pressed="true" />

</selector>

  • 在layout文件中使用
   <TextView
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:layout_margin="20dp"
        android:background="@drawable/bgc_btn"
        android:clickable="true"
        android:gravity="center"
        android:text="selector+shape方式"
        android:textColor="@drawable/color_text" />       
  • 效果
ButtonText.gif

2. 自定义Button

 <lu.example.ButtonTextView
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:layout_margin="20dp"
        android:background="#ff0000"
        android:gravity="center"
        android:text="自定义方式"
        android:textColor="@android:color/white"
        app:corner="30%"
        app:pressBgc="#008888"
        app:pressTxtColor="#000"
        app:stroke="10px" />
        
  • 效果
ButtonText2.gif zongjie.png

从上面两种方式可以看出通过自定义button的方式可以很方便地实现按钮样式的指定,免去了写selector和shape的麻烦,最重要的是每个selector和shape都是固定的值,如果颜色需要改变,不同的样式需要写不同的selector,这是很不方便的,哪怕只是改一个圆角大小或者边框粗细。

一、ButtonTextView的实现思路

在看一下我们上面使用的代码

<lu.example.ButtonTextView
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:layout_margin="20dp"
        android:background="#ff0000"
        android:gravity="center"
        android:text="自定义方式"
        android:textColor="@android:color/white"
        app:corner="30%"
        app:pressBgc="#008888"
        app:pressTxtColor="#000"
        app:stroke="10px" />
        
-----------------------------------------------------

1.background  和 textColor两个是本身就有的属性   用来设置默认情况下背景颜色和字体颜色,这个保持不变

2.  app:corner="30%"//可以是具体数值,也可以是边框的百分比
    app:pressBgc="#008888"//可以是具体颜色,也可以用@color/red的方式
    app:pressTxtColor="#000"
    app:stroke="10px"//边框默认的颜色和正常文字颜色一样
    
    四个自定义属性  从名字即可看出他们的作用
        
        
  1. 自定义属性

在res/values.xml中定义四个属性

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="ButtonTextView">
        <attr name="pressTxtColor" format="color"></attr>
        <attr name="pressBgc" format="color"></attr>
        <attr name="stroke" format="dimension"></attr>
        <attr name="corner" format="dimension|fraction"></attr>
    </declare-styleable>
</resources>

自定义属性值的获取


//首先定义NAME_SPACE和属性用于获取原来就有的background和textColor
  private final String NAME_SPACE = "http://schemas.android.com/apk/res/android";
    private final String ATTR_BGC = "background";
    private final String ATTR_TXTC = "textColor";


//在构造方法中获取属性

 public ButtonTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();

        if (attrs != null) {
            String bc = attrs.getAttributeValue(NAME_SPACE, ATTR_BGC);
            if (TextUtils.isEmpty(bc)) {
                bgc = Color.WHITE;
            } else if (bc.startsWith("#")) {
                bgc = Color.parseColor(bc);
            } else if (bc.startsWith("@")) {
                bgc = ContextCompat.getColor(context, Integer.valueOf(bc.substring(1)));
            }

            String tc = attrs.getAttributeValue(NAME_SPACE, ATTR_TXTC);
            if (TextUtils.isEmpty(tc)) {
                txtC = DEFAULT_TEXT_COLOR;
            } else if (tc.startsWith("#")) {
                txtC = Color.parseColor(tc);
            } else if (tc.startsWith("@")) {
                txtC = ContextCompat.getColor(context, Integer.valueOf(tc.substring(1)));
            }

        }

        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ButtonTextView);

        pressTxtC = ta.getColor(R.styleable.ButtonTextView_pressTxtColor, txtC);
        pressBgc = ta.getColor(R.styleable.ButtonTextView_pressBgc, bgc);

        //处理圆角度
        final String cornerValue = ta.getString(R.styleable.ButtonTextView_corner);
        if (!TextUtils.isEmpty(cornerValue)) {
            if (cornerValue.contains("%")) {
                corner = -1;
                cornerPercent = ta.getFraction(R.styleable.ButtonTextView_corner, 1, 1, 0f);
            } else {
                corner = ta.getDimensionPixelSize(R.styleable.ButtonTextView_corner, 0);
            }
        }

        //处理边框
        stroke = ta.getDimensionPixelSize(R.styleable.ButtonTextView_stroke, 0);

        ta.recycle();
    }


构建字体颜色ColorStateList的方法

/**
 * 
 * @param txtC 正常情况下的字体颜色
 * @param pressTxtC 按下时的字体颜色
 */
 private void setTxtColor(@NonNull int txtC, @NonNull int pressTxtC) {

        if (txtC == pressTxtC) {
            setTextColor(txtC);
            return;
        }

        int[] colors = new int[]{pressTxtC, txtC};

        int[][] states = new int[2][];
        states[0] = new int[]{android.R.attr.state_pressed};
        states[1] = new int[]{};

        ColorStateList colorStateList = new ColorStateList(states, colors);

        setTextColor(colorStateList);
    }

构建背景色StateListDrawable的方法

 /**
     *
     * @param bgc 正常背景色
     * @param pressBgc 按下背景色
     * @param corner 圆角
     * @param stroke 边框
     */
    private void setBgcDrawable(@NonNull int bgc, @NonNull int pressBgc, float corner, int stroke) {

        GradientDrawable bgcDrawable = new GradientDrawable();
        GradientDrawable pBgcDrawable = new GradientDrawable();

        bgcDrawable.setCornerRadius(corner);
        bgcDrawable.setStroke(stroke, txtC == 0 ? DEFAULT_TEXT_COLOR : txtC);
        bgcDrawable.setColor(bgc);


        if (bgc == pressBgc) {
            setBackgroundDrawable(bgcDrawable);
            return;
        }

        pBgcDrawable.setCornerRadius(corner);
        pBgcDrawable.setStroke(stroke, pressBgc);
        pBgcDrawable.setColor(pressBgc);

        StateListDrawable stateListDrawable = new StateListDrawable();
        stateListDrawable.addState(new int[]{android.R.attr.state_pressed}, pBgcDrawable);
        stateListDrawable.addState(new int[]{}, bgcDrawable);

        setBackgroundDrawable(stateListDrawable);
    }

具体设置字体颜色和背景色的代码这里选择在onSizeChanged()方法中调用

  @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        if (corner < 0) {
            corner = cornerPercent * h;
        }
        setBgcDrawable(bgc, pressBgc, corner, stroke);
        setTxtColor(txtC, pressTxtC);
    }

附整体代码(使用时需要添加自定义属性)

/**
 * 自定义按下颜色和边框的TextView
 * Created by lqh on 2016/9/25.
 */
public class ButtonTextView extends AppCompatTextView {

    private final String NAME_SPACE = "http://schemas.android.com/apk/res/android";
    private final String ATTR_BGC = "background";
    private final String ATTR_TXTC = "textColor";

    private final int DEFAULT_TEXT_COLOR = 0x8a000000;
    //文字演策
    private int txtC = DEFAULT_TEXT_COLOR;
    private int pressTxtC = DEFAULT_TEXT_COLOR;
    //背景色
    private int bgc;
    private int pressBgc;
    //圆角
    private float corner;
    private float cornerPercent;
    //边框
    private int stroke;

    /* 通过代码创建对象时,不检索自定义属性*/
    public ButtonTextView(Context context) {
        super(context);
        /*默认颜色*/
        setTextColor(DEFAULT_TEXT_COLOR);
    }

    public ButtonTextView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ButtonTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();

        if (attrs != null) {
            String bc = attrs.getAttributeValue(NAME_SPACE, ATTR_BGC);
            if (TextUtils.isEmpty(bc)) {
                bgc = Color.WHITE;
            } else if (bc.startsWith("#")) {
                bgc = Color.parseColor(bc);
            } else if (bc.startsWith("@")) {
                bgc = ContextCompat.getColor(context, Integer.valueOf(bc.substring(1)));
            }

            String tc = attrs.getAttributeValue(NAME_SPACE, ATTR_TXTC);
            if (TextUtils.isEmpty(tc)) {
                txtC = DEFAULT_TEXT_COLOR;
            } else if (tc.startsWith("#")) {
                txtC = Color.parseColor(tc);
            } else if (tc.startsWith("@")) {
                txtC = ContextCompat.getColor(context, Integer.valueOf(tc.substring(1)));
            }

        }

        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ButtonTextView);

        pressTxtC = ta.getColor(R.styleable.ButtonTextView_pressTxtColor, txtC);
        pressBgc = ta.getColor(R.styleable.ButtonTextView_pressBgc, bgc);

        //处理圆角度
        final String cornerValue = ta.getString(R.styleable.ButtonTextView_corner);
        if (!TextUtils.isEmpty(cornerValue)) {
            if (cornerValue.contains("%")) {
                corner = -1;
                cornerPercent = ta.getFraction(R.styleable.ButtonTextView_corner, 1, 1, 0f);
            } else {
                corner = ta.getDimensionPixelSize(R.styleable.ButtonTextView_corner, 0);
            }
        }

        //处理边框
        stroke = ta.getDimensionPixelSize(R.styleable.ButtonTextView_stroke, 0);

        ta.recycle();
    }

    private void init() {
        setClickable(true);
    }


    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        if (corner < 0) {
            corner = cornerPercent * h;
        }
        setBgcDrawable(bgc, pressBgc, corner, stroke);
        setTxtColor(txtC, pressTxtC);
    }

    /**
     *
     * @param txtC 正常情况下的字体颜色
     * @param pressTxtC 按下时的字体颜色
     */
    private void setTxtColor(@NonNull int txtC, @NonNull int pressTxtC) {

        if (txtC == pressTxtC) {
            setTextColor(txtC);
            return;
        }

        int[] colors = new int[]{pressTxtC, txtC};

        int[][] states = new int[2][];
        states[0] = new int[]{android.R.attr.state_pressed};
        states[1] = new int[]{};

        ColorStateList colorStateList = new ColorStateList(states, colors);

        setTextColor(colorStateList);
    }


    /**
     *
     * @param bgc 正常背景色
     * @param pressBgc 按下背景色
     * @param corner 圆角
     * @param stroke 边框
     */
    private void setBgcDrawable(@NonNull int bgc, @NonNull int pressBgc, float corner, int stroke) {

        GradientDrawable bgcDrawable = new GradientDrawable();
        GradientDrawable pBgcDrawable = new GradientDrawable();

        bgcDrawable.setCornerRadius(corner);
        bgcDrawable.setStroke(stroke, txtC == 0 ? DEFAULT_TEXT_COLOR : txtC);
        bgcDrawable.setColor(bgc);


        if (bgc == pressBgc) {
            setBackgroundDrawable(bgcDrawable);
            return;
        }

        pBgcDrawable.setCornerRadius(corner);
        pBgcDrawable.setStroke(stroke, pressBgc);
        pBgcDrawable.setColor(pressBgc);

        StateListDrawable stateListDrawable = new StateListDrawable();
        stateListDrawable.addState(new int[]{android.R.attr.state_pressed}, pBgcDrawable);
        stateListDrawable.addState(new int[]{}, bgcDrawable);

        setBackgroundDrawable(stateListDrawable);
    }

    /**
     * 设置背景色
     *
     * @param bgc
     * @param pressBgc
     */
    public void setBgcDrawable(@NonNull int bgc, @NonNull int pressBgc) {
        this.bgc = bgc;
        this.pressBgc = pressBgc;
    }

    /**
     * 设置文字颜色
     *
     * @param txtC
     * @param pressTxtC
     */
    public void setTextColor(@NonNull int txtC, @NonNull int pressTxtC) {
        this.txtC = txtC;
        this.pressTxtC = pressTxtC;
    }

    public void setCorner(float corner) {
        this.corner = corner;
    }

    public void setStroke(int stroke) {
        this.stroke = stroke;
    }

    public void setTxtC(int txtC, int pressTxtC) {
        this.txtC = txtC;
        this.pressTxtC = pressTxtC;
    }

如果错误欢迎指正,感谢!

相关文章

  • 自定义button 可设置圆角 边框 按下颜色

    一、为什么要自定义这样的Button 在Android开发中,按钮是最经常使用的控件,按钮所涉及的样式无非几种 边...

  • 使用BezierPath设置圆角和边框颜色

    为了避免离屏渲染,我用UIBezierPath给UIButton设置了圆角。但是给button的边框设置颜色时遇到...

  • xib中设置按钮的边框颜色

    首先,说一下如何在xib中设置Button的边框及圆角效果: 选中要设置的Button, 切换到图中对应位置,点击...

  • Xcode 设置按钮的边框颜色

    首先,说一下如何在xib中设置Button的边框及圆角效果:选中要设置的Button, 切换到图中对应位置,点击加...

  • 直接在IB上设置控件圆角边框

    直接在IB界面设置圆角边框颜色 运行结果 可以看到直接在xib中属性设置的圆角边框成功啦! 贴一下代码.h 贴一下...

  • CALayer

    1. 获取View的CALayer 设置边框宽度 设置边框颜色 设置圆角 设置内容 Question: 这样设置完...

  • QQ粘性布局

    按钮button自定义button设置圆角半径cornerRadius取消高亮状态重写setHighlighted...

  • ios 项目中常遇到的问题 持续更新中···

    1、Button 设置圆角 边框问题 2、NavigationController 跳转至指定界面 3、UILa...

  • Image

    直接圆角图片 设置圆角图片度数 设置圆角图片带灰色圆角边框 设置圆角图片带灰色圆角边框带阴影

  • 边框效果-css-v1.0.0

    半透边框 通过设置颜色的透明度实现。 框内圆角 方式1:为元素设置圆角,外层设置轮廓outline。圆角与直角之间...

网友评论

      本文标题:自定义button 可设置圆角 边框 按下颜色

      本文链接:https://www.haomeiwen.com/subject/efuhhxtx.html