Android自定义状态选择器属性

其实,android已经给我们提供了比较丰富的状态选择器属性了,比如android:state_checked、android:state_pressed、android:state_selected、android:state_enabled等等,相信大家都不陌生,我今天要介绍的并不是如何使用这些属性,而是教大家如何创建自定义的状态属性。比如我要创建定义一个名字叫state_on的属性,值是一个布尔值,这也是可以实现的。

下图展示了今天的demo例子:
这里写图片描述

例子中的图片和文字都有2种状态,不同的状态对应了不同的样式,该状态的属性是一个自定义的。

下面介绍下实现步骤:
1.首先得声明这个自定义属性的name和format,在res/values目录下,创建一个xml文件,例如custom_status.xml,内容如下:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="CustomStatus">
        <attr name="state_on" format="boolean" />
    </declare-styleable>
</resources>

2.创建一个容器,通过该容器将自定义的状态属性与其关联,然后对外暴露方法来改变自定义属性的状态.

package mchenys.net.csdn.blog.customstatedemo;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.RelativeLayout;

/**
 * 自定义状态的布局
 * Created by mChenys on 2018/4/26.
 */

public class MyCustomStateLayout extends RelativeLayout {

    private boolean isStateOn; //状态是否开启
    //自定义状态属性
    private static final int[] MY_STATE= {R.attr.state_on};

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

    }
    /**
     * 对外暴露方法,改变自定义属性的状态
     * @param stateOn
     */
    public void setStateOn(boolean stateOn) {
        if (this.isStateOn != stateOn) {
            isStateOn = stateOn;
            refreshDrawableState();//刷新状态
        }
    }

    @Override
    protected int[] onCreateDrawableState(int extraSpace) {
        if (isStateOn) {
            final int[] drawableState = super
                    .onCreateDrawableState(extraSpace + 1);
            //加入自定义的状态属性
            mergeDrawableStates(drawableState, MY_STATE);
            return drawableState;
        }
        return super.onCreateDrawableState(extraSpace);
    }


    public boolean isStateOn() {
        return isStateOn;
    }
}

3.至此,就可以试用这个属性来创建选择器了,在本例中,我创建了2个选择器,一个是TextView的color选择器,另一个是ImageView的drawable选择器,分别如下:
res/color/cus_state_font_color.xml

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

    <item android:color="@color/colorAccent" cys:state_on="true"/>
    <item android:color="@color/colorPrimary" />

</selector>

res/drawable/cus_state_img_bg.xml

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

    <item android:drawable="@drawable/ic_state_on" cys:state_on="true"/>
    <item android:drawable="@drawable/ic_launcher"/>

</selector>

最后,就是使用这2个选择器了,在res/layout/activity_main.xml内容如下:

<?xml version="1.0" encoding="utf-8"?>
<mchenys.net.csdn.blog.customstatedemo.MyCustomStateLayout
    android:id="@+id/mcsl"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingVertical="20dp"
    android:paddingHorizontal="10dp">

    <!--android:duplicateParentState="true"
        作用是为了让子View的状态和父View同步
    -->

    <ImageView
        android:id="@+id/iv"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="@drawable/cus_state_img_bg"
        android:duplicateParentState="true"
        />


    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/iv"
        android:layout_marginLeft="5dp"
        android:layout_toRightOf="@+id/iv"
        android:duplicateParentState="true"
        android:text="Hello World!"
        android:textColor="@color/cus_state_font_color"
        android:textSize="30sp"
        />

    <CheckBox
        android:id="@+id/cb"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/iv"
        android:layout_alignParentRight="true"
        android:text="开启"/>
</mchenys.net.csdn.blog.customstatedemo.MyCustomStateLayout>

注意,TextView和ImageView的状态改变其实通过它们的父View,即MyCustomStateLayout来改变的,前提是子View需要设置android:duplicateParentState=”true”属性,代码有注释,另一个原因就是MyCustomStateLayout有对外暴露改变状态的方法。当然如果你想改变的是MyCustomStateLayout自身也是可以的,这点比较符合我们使用的习惯,只需在MyCustomStateLayout上使用选择器就可以,比如加一个背景颜色选择器,或者其他你喜欢的都可以,但是别忘了在选择器中要使用我们自定义的属性,才能看到想要的效果。

ok,上面的布局已经设置好了选择器,那么如何触发呢?在本例中,我是通过布局中的checkbox的勾选状态变化来控制MyCustomStateLayout的状态,代码如下:
MainActivity.java

package mchenys.net.csdn.blog.customstatedemo;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.CheckBox;
import android.widget.CompoundButton;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        CheckBox checkBox = findViewById(R.id.cb);
        final MyCustomStateLayout mcsl = findViewById(R.id.mcsl);
        checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if (isChecked) {
                    buttonView.setText("关闭");
                    mcsl.setStateOn(true);
                }else{
                    buttonView.setText("开启");
                    mcsl.setStateOn(false);
                }
            }
        });
    }
}

当然,你也可以重写MyCustomStateLayout的onTouchEvent,当ACTION_DOWN的时候将状态改为true,这个就随你们喜欢了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值