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