1. 程式人生 > >Android自定義狀態選擇器屬性

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,這個就隨你們喜歡了。