您的位置:首页 > 移动开发 > Android开发

Android-自定义反色圆角Button

2015-09-02 17:52 531 查看
学习目标:

                掌握使用 <shape> 标签和 <selector> 标签 在 Button 视图上的使用。

                掌握使用代码代替xml文件的功能,实现同上效果。

                掌握自定义属性的使用。

                写一个自定义Button配合自定义属性,完成反色效果。

1.> <shape> 标签 与 <selector> 标签

在 drawable 文件夹下新建一个button_shape.xml文件,来对 shape 进行描述

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<!-- 圆角半径,越大,则角越圆,越小则角越方 -->
<corners android:radius="5dp"/>
<!-- 描边线   -->
<stroke android:width="5dp" android:color="#6699FF"/>
<!-- 填充 -->
<solid android:color="#6699FF"/>
</shape>


写完之后,便可以在布局文件中,使用 backgroud 来引用这个 shape了

<Button
android:text="普通按钮"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#ffffff"
<strong>android:background="@drawable/button_shape"</strong>/>


效果如图所示,非常简单



因为Button是可点击的,每一次对 Button进行触碰的时候,都会改变它的状态。

我们可以通过为 Button 的 backgroud 指定一个 处理方案<selector>,来告诉 Button,对于哪一样的状态,用什么用的背景图

drawable >> while_button.xml

<?xml version="1.0" encoding="utf-8" ?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" android:drawable="@drawable/white_radius_clicking_button"/>
    <item android:state_pressed="false" android:drawable="@drawable/white_radius_button"/>
    <!-- 默认时的背景图片-->  
    <item android:drawable="@drawable/white_radius_button" />
</selector>


针对于反色,我们设定在默认状体下,Button的形状为:蓝色描边线,白底填充,蓝色字体.

drawable >> white_radius_button.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<stroke android:width="1dp" android:color="#6699FF"/>
<corners android:radius="5dp"/>
<solid android:color="@android:color/white"/>
</shape>


                          

                           当我们点击的时候,修改对应的状态为: 蓝色描边线,蓝色填充,白色字体.

drawable >> white_radius_clicking_button.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<corners android:radius="5dp"/>
<solid android:color="#6699FF"/>
<stroke android:width="1dp" android:color="#6699FF"/>
</shape>


当然,如上只是设置了Button的形状,但是对于 Button中文字的颜色也需要进行配置.

drawable >> white_font.xml

<?xml version="1.0" encoding="utf-8" ?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:color="#ffffff"/>
<item android:state_pressed="false" android:color="#6699FF"/>
<item android:color="#6699FF" />
</selector>


OK,为Button添加backgroud,以及textcolor

<Button android:text="蓝白反色按钮"
android:layout_width="match_parent"
android:layout_height="wrap_content"
<strong>android:textColor="@drawable/white_font"
android:background="@drawable/while_button"</strong>/>


效果如图所示:



2.> StateListDrawable 和 ColorStateList

         同样的效果,可以使用代码来实现。

         可以使用 GradientDrawable 来代替 Shape.

         创建一个继承Button的视图,并在其构造函数中编码:

        

// 相当于创建了 shape
GradientDrawable gd = new GradientDrawable();
// 设置 shape 的填充色
gd.setColor(Color.BLACK);
// 设置 shape 的圆角
gd.setCornerRadius(10);
// 设置 shape 的描边线的宽度和颜色
gd.setStroke(1, Color.BLACK);
setBackground(gd);


        同样的,使用 StateListDrawable 来代替使用xml来配置 Button在不同状态下的背景图

StateListDrawable statelistDrawable = new StateListDrawable();
int pressed = android.R.attr.state_pressed;
int windowfocused = android.R.attr.state_window_focused;

// -pressed 相当于 false
statelistDrawable.addState(new int[] { pressed, windowfocused },drable0); 
statelistDrawable.addState(new int[] { -pressed,windowfocused },drable1);

<pre name="code" class="java">setBackground(statelistDrawable);




了解了这个类的相关使用,就可以在代码中同样实现反色效果了。

// 定义一个默认填充色
int inverseColor = Color.BLACK;

// 统一的圆角半径
int roundRadius = 10;
// 统一的描边线的宽度
int strokeWidth = 1;
// 描边线的颜色
int strokeColor = inverseColor;

/* 先设定默认情况下的形状 */
// 默认状态下的填充色为白色
int defaultFillColor = Color.parseColor("#ffffff");
GradientDrawable defaultGd = new GradientDrawable();

defaultGd.setColor(defaultFillColor);
defaultGd.setCornerRadius(roundRadius);
defaultGd.setStroke(strokeWidth, strokeColor);

/* 再设定按下情况下的形状 */
// 设置反色为我们定义的颜色
int pressedFillColor = inverseColor;
GradientDrawable pressedGd = new GradientDrawable();
pressedGd.setColor(pressedFillColor);
pressedGd.setCornerRadius(roundRadius);
pressedGd.setStroke(strokeWidth, strokeColor);

StateListDrawable statelistDrawable = new StateListDrawable();
int pressed = android.R.attr.state_pressed;
int windowfocused = android.R.attr.state_window_focused;

// 分别为不同的状态装配不同的背景
// "-"号表示该状态值为false .即不匹配
statelistDrawable.addState(new int[] { pressed, windowfocused },pressedGd);
statelistDrawable.addState(new int[] { -pressed,windowfocused },defaultGd);

setBackground(statelistDrawable);

// <span style="font-size:18px;"><strong>另外还需要设置一下字体的颜色的反色效果</strong></span>
int[] unpress = new int[]{-pressed,windowfocused};
int[] btnPressed = new int[]{pressed, windowfocused};
int[][] states = new int[][]{unpress,btnPressed };
int[] colors = new int[]{inverseColor,Color.parseColor("#ffffff")};
ColorStateList colorStateList = new ColorStateList(states, colors);
this.setTextColor(colorStateList);


再布局文件中加入我们自定义的这个Button,可以看到效果:



3.> attrs.xml 文件的使用

很明显,我们不可能为了不同的颜色效果专门写xml文件,或者重新自定义Button.这样我们就需要在使用我们自定义Button的时候,

为其传入我们想要的反色。然后再构建函数中获取我们传入的值,然后再将其作用到Button上.

这样我们就需要自定义属性来帮帮忙了.

第一步. values>>attrs.xml  定义我们想要的属性

<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- 属性集的名 -->
<declare-styleable name="inverseColBtn">
<!-- 属性名 , 及属性值的格式 -->
<attr name="inverseColor" format="color"/>
<attr name="whiteFillFirst" format="boolean" />
</declare-styleable>
</resources>


第二步,在布局文件中,让视图使用这个属性

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:myStyle="http://schemas.android.com/apk/res/com.example.buttons"
android:layout_width="match_parent"
android:layout_height="match_parent"

.......>

<zy.pointer.custom.InverseColButton android:text="InversColBtn"
        myStyle:inverseColor="@android:color/black"
        myStyle:whiteFillFirst="false"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
     />


首先是申明一个别名

xmlns:myStyle="http://schemas.android.com/apk/res/com.example.buttons"


myStyle 就是这个别名,它将在后面使用,可以随便写

http://schemas.android.com/apk/res/com.example.buttons
这一部分呢,前面的照写,后面的那一段就是我们工程的包名

再然后就是再我们自定义的组件上写我们的自定义属性了。

myStyle:inverseColor="@android:color/black"
myStyle:whiteFillFirst="false"


myStyle就是我们申明的别名了,后面的属性名就不要乱写了。是 attrs.xml 中定义的属性集中的属性名

第三步,获取我们的自定义属性的值。

public InverseColButton(Context context, AttributeSet attrs) {
super(context, attrs);

//TypedArray是一个数组容器
//先让属性集的名字
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.inverseColBtn);
//防止在XML文件里没有定义,就加上了默认值
//再放属性集里面定义的属性名
int inverseColor = a.getColor(R.styleable.inverseColBtn_inverseColor, Color.BLACK);
boolean whiteFillFirst = a.getBoolean(R.styleable.inverseColBtn_whiteFillFirst, true);

.......


4.> InverseColButton

         我们定义了两个特别的属性:

<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- 属性集的名 -->
<declare-styleable name="inverseColBtn">
<!-- 属性名 , 及属性值的格式 -->
<attr name="inverseColor" format="color"/>
<attr name="whiteFillFirst" format="boolean" />
</declare-styleable>
</resources>
       

其中 inverseColor 是我们希望的反色效果使用的颜色

whiteFillFirst 是说是否使用白色首先作为填充色。这个值的作用,我放在这里的期望是,将反色效果倒置一下.

直接上 InverseColButton 的代码吧。

public class InverseColButton extends Button{

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
    
    
    public InverseColButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        
        //TypedArray是一个数组容器  
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.inverseColBtn);
        //防止在XML文件里没有定义,就加上了默认值,默认反色使用黑色,默认首先使用白色进行填充.
        int inverseColor = a.getColor(R.styleable.inverseColBtn_inverseColor, Color.BLACK);
        boolean whiteFillFirst = a.getBoolean(R.styleable.inverseColBtn_whiteFillFirst, true);
        
        // 统一的圆角半径
        int roundRadius = 10;
        // 统一的描边线的宽度
        int strokeWidth = 1;
        // 描边线的颜色
        int strokeColor = inverseColor;
        
        /* 先设定默认情况下的形状 */
        // 默认状态下的填充色
        int defaultFillColor = Color.WHITE;
        GradientDrawable whiteFillGd = new GradientDrawable();
        whiteFillGd.setColor(defaultFillColor);
        whiteFillGd.setCornerRadius(roundRadius);
        whiteFillGd.setStroke(strokeWidth, strokeColor);
        
        /* 再设定按下情况下的形状 */
        int pressedFillColor = inverseColor;
        GradientDrawable inverseGd = new GradientDrawable();
        inverseGd.setColor(pressedFillColor);
        inverseGd.setCornerRadius(roundRadius);
        inverseGd.setStroke(strokeWidth, strokeColor);
        
        
        StateListDrawable statelistDrawable = new StateListDrawable();  
        int pressed = android.R.attr.state_pressed;  
        int windowfocused = android.R.attr.state_window_focused;  
        // 如果使用白色首先填充,则和以前一样
        if(whiteFillFirst){
            statelistDrawable.addState(new int[] { pressed, windowfocused },inverseGd);  
            statelistDrawable.addState(new int[] { -pressed,windowfocused },whiteFillGd);
        }else{
            // 否则就是反着的效果
            statelistDrawable.addState(new int[] { pressed, windowfocused },whiteFillGd);  
            statelistDrawable.addState(new int[] { -pressed,windowfocused },inverseGd);
        }
        setBackground(statelistDrawable);
        
        // 另外还需要设置一下字体的颜色的反色效果
        int[] unpress = new int[]{-pressed,windowfocused};
        int[] pressing = new int[]{pressed, windowfocused};
        int[][] states = new int[][]{unpress,pressing};
        int[] colors;
        // 同样的,字体的颜色要和上面的一致.
        if(whiteFillFirst){
            colors = new int[]{inverseColor,Color.WHITE};
        }else{
            colors = new int[]{Color.WHITE,inverseColor};
        }
        ColorStateList colorStateList = new ColorStateList(states, colors);
        this.setTextColor(colorStateList);
    }    
}



添加Button,让它们显示一下相反的效果给大伙看看

<zy.pointer.custom.InverseColButton android:text="InversColBtn - true"
myStyle:inverseColor="#800080"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>

<zy.pointer.custom.InverseColButton android:text="InversColBtn - false"
myStyle:inverseColor="#800080"
<strong>myStyle:whiteFillFirst="false"</strong>
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>




另外给大家分享一个常用颜色值;

      
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: