標籤:
android的selector對於android開發人員而言再熟悉不過了,只要定義一個drawable目錄下定義一個selector的xml檔案,在布局檔案中background引用這個xml檔案或者在代碼中setBackgroundDrawable的時候使用此xml就可以實現控制項按下或有焦點或啟用狀態等不同狀態的效果。你真的對selector的使用全瞭解嗎?
前言
項目中確實用到了像多個標籤,然後選中規格要給文字的邊框加點顏色,對於長度和個數不確定的情況呢我們通常可以在代碼中通過資料的長度動態new一個控制項然後給他們加點擊事件,並且給每個控制項設定背景是可以實現的,但是使用grideView的話還是不好實現,所以呢就搜了下發現state_activated能夠完美的實現此功能。
效果如下
安卓4.4下效果:
安卓5.1效果
selector屬性介紹
selector 的根節點必須是item、可以包含一個或多個item元素
xmlns:android String、必須、定義XML的命名空間、必須是 “http://schemas.android.com/apk/res/android”
android:state_pressed
Boolean、“true”表示按下狀態使用(例如按鈕按下)、“false”表示非按下狀態使用
android:state_focused
Boolean、“true”表示聚焦狀態使用(例如使用聚焦Button);“false”表示非聚焦狀態使用
android:state_selected
Boolean、“true”表示選中狀態使用(例如Tab 開啟);“false” 表示非選中狀態使用
android:state_enabled設定是否響應事件,指所有事件
哈哈,上面的屬性你是否經常使用,因為我們的需求一般都是有無焦點有無按下來改變圖片的文字和背景顏色,然後呢,比如listView和grideView點擊後狀態保留你可能不一定使用過。
android:state_checkable
Boolean、“true”表示可勾選狀態時使用;“false”表示非可 勾選狀態使用、(只對能切換可勾選—非可勾選的構件有用)
android:state_hovered
這個是api14以上才有的,這個是當游標移動到某一個組件之上的時候的狀態,到目前為止,還沒有看見過哪個手機裝置帶有滑鼠之類的東西,可能這個專門是為平板電腦設定的或者以後可能出現帶有滑鼠之類的裝置而準備的吧,文檔中說,一般這個值設定為與focused這個值一樣。
android:state_window_focused
這個是是否對當前介面是否得到焦點的兩種狀態的設定,所以呢一般我們都是用不到的
android:state_activated
表示當前控制項被啟用的狀態,這個呢或許很多安卓開發人員都沒有用過,然後呢它可以保留被按下的狀態
詳細的請看官方的API,那裡寫的更詳細http://developer.android.com/guide/topics/resources/drawable-resource.html#StateList
selector的執行個體使用
一般selector的作用呢就是給view控制項設定背景前景等,因為selector本意呢根據狀態的不同為同一個圖形更換不同的圖片。然後呢使用StateListDrawable來代替普通的drawable,具體的drawable的繪製你可以參考Android的各種Drawable講解,所以呢drawable可以是color,shape,img,今天的重點不是要去繪製drawable而是去使用selector。
給cardView設定selector(state_pressed使用)
我相信很多人使用過CardView,現在呢我們給它加一個前景selector
<android.support.v7.widget.CardView xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="8dp" android:foreground="@drawable/card_foreground" android:id="@+id/cv_item" android:elevation="2dp" app:cardCornerRadius="4dp" app:cardBackgroundColor="@android:color/white" app:cardPreventCornerOverlap="false" app:cardUseCompatPadding="true" android:clickable="true"> <TextView android:id="@+id/text_view" android:padding="20dp" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:text="selector 按下鬆開效果"/> </android.support.v7.widget.CardView>
要設定selector的前提呢,我們得準備drawable,然後cardView我們給它設定selector就得區分5.0之前和之後的效果,我們都知道5.0後點擊會有水波紋效果(ripple ),然後之前我們並沒有此效果。
然後我們怎麼去設定呢:
drawable檔案下適配
card_foreground.xml
<?xml version="1.0" encoding="utf-8"?><inset xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@drawable/card_foreground_selector" android:insetLeft="2dp" android:insetRight="2dp" android:insetTop="4dp" android:insetBottom="4dp"/>
card_foreground_selector.xml
<?xml version="1.0" encoding="utf-8"?><selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="true"> <shape android:shape="rectangle"> <solid android:color="#e0F5AD6E"/> <corners android:radius="@dimen/card_radius" /> </shape> </item> <item android:state_focused="true" android:state_enabled="true"> <shape android:shape="rectangle"> <solid android:color="#0f000000"/> <corners android:radius="@dimen/card_radius" /> </shape> </item></selector>
drawable-v21檔案下適配
card_foreground.xml
<?xml version="1.0" encoding="utf-8"?><ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="#F5AD6E" android:drawable="@drawable/card_foreground_selector" />
card_foreground_selector.xml
<?xml version="1.0" encoding="utf-8"?><selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="true"> <shape android:shape="rectangle"> <solid android:color="#F5AD6E"/> </shape> </item> <item android:state_focused="true" android:state_enabled="true"> <shape android:shape="rectangle"> <solid android:color="#0f000000"/> </shape> </item></selector>
什麼ripple和inset 並不是重點,重點是我們如何去寫selector檔案,其實呢特別簡單,你有多少個狀態就用item分開好了,接著為各種狀態下配置drawable好了,這裡呢我直接把shape作為drawable使用了。
grideView的item按下狀態保留(state_activated)
其實沒有碰到這種情況的時候我也沒有去注意state_activated使用,哈哈,確實給開發帶來了很大的方便。
當我們發現selector中的state_selected不起作用:注意state_activated狀態,作用是啟用view後狀態一直到保留,除非啟用狀態被取消,所以必須指定android:state_activated為true或者false。
gride_selector.xml
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_activated="false"> <shape xmlns:android="http://schemas.android.com/apk/res/android" > <!-- 線的寬度,顏色灰色 --> <stroke android:width="1dp" android:color="#A3A3A3"></stroke> <!-- 矩形的圓角半徑 --> <corners android:radius="4dp" /> </shape> </item> <item android:state_pressed="true"> <shape xmlns:android="http://schemas.android.com/apk/res/android" > <!-- 線的寬度,顏色灰色 --> <stroke android:width="1dp" android:color="#ffea5514"></stroke> <!-- 矩形的圓角半徑 --> <corners android:radius="4dp" /> </shape> </item> <item android:state_activated="true"> <shape xmlns:android="http://schemas.android.com/apk/res/android" > <!-- 線的寬度,顏色灰色 --> <stroke android:width="1dp" android:color="#ffea5514"></stroke> <!-- 矩形的圓角半徑 --> <corners android:radius="4dp" /> </shape> </item></selector>
哈哈寫完了,我們就可以加到grideView的item布局裡面,具體的是加在根布局下還是具體的控制項下都是可以的。
好了,我們來看看activity的代碼:
package com.losileeya.selectmaster;import android.os.Bundle;import android.support.design.widget.Snackbar;import android.support.v7.app.AppCompatActivity;import android.view.View;import android.widget.AdapterView;import android.widget.GridView;import com.losileeya.selectmaster.adapter.TagAdapter;import java.util.ArrayList;import java.util.List;import butterknife.BindView;import butterknife.ButterKnife;public class MainActivity extends AppCompatActivity { @BindView(R.id.gridview) GridView gridview; private TagAdapter mAdapter; private List<String>mDatas; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ButterKnife.bind(this); initData(); doEvent(); } private void initData() { mDatas=new ArrayList<>(); mDatas.add("東方財富?理財"); mDatas.add("58 同 城"); mDatas.add("搜 房 網"); mDatas.add("攜程旅行網"); mDatas.add("百度地圖"); mDatas.add("12306?旅遊"); mDatas.add("世紀佳緣"); mDatas.add("趕 集 網"); mDatas.add("易 車 網"); mDatas.add("去哪兒網"); mDatas.add("唯 品 會"); } private void doEvent() { gridview.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Snackbar.make(gridview,mDatas.get(position), Snackbar.LENGTH_SHORT) .show(); } }); gridview.setChoiceMode(GridView.CHOICE_MODE_SINGLE);// 單選模式 // 預設第一個item被選中 mAdapter = new TagAdapter(MainActivity.this, mDatas, 0); gridview.setAdapter(mAdapter); gridview.post(new Runnable() { @Override public void run() { gridview.setItemChecked(0, true); gridview.setSelected(true); gridview.setSelection(0); } }); }}
看上面的代碼可知:大體實現步驟
1.GridView中的表徵圖在drawable中寫出selector,該selector檔案中列出了android:state_pressed的圖片資源、state_selected的圖片資源。
2.gridview.setChoiceMode(GridView.CHOICE_MODE_SINGLE);// 單選模式
3.GridView的onItemClickedListener監聽裡,針對當前選擇的view,調用view.selected(true)
4.gridview.setItemChecked(0, true);gridview.setSelection(0);預設選中第一個
注意事項
selector.xml中的state_activated狀態屬性必須在androidAPI-11及以上版本使用。
寫到這裡就寫完了,基本上都是項目中能夠用到的(check這裡沒講,使用差不多不多講)不知道對你有什麼協助,雖然很簡單是不是對selector的理解更進一步。
demo傳送門:SelectMaster.rar
安卓實戰開發之CardView的selector及GrideView的item按下狀態保留selector(state_activated)的實現