View繪制流程之Drawable(二)

Drawable

在上篇筆記中簡(jiǎn)要的闡述了下個(gè)人對(duì)Drawable的理解梅誓,該篇筆記是對(duì)Drawable中的StateListDrawable實(shí)踐步清。

StateListDrawable

shape標(biāo)簽只能定義不同的形狀,而selector標(biāo)簽則可以根據(jù)控件的狀態(tài)顯示不同形狀亩码。例如一個(gè)按鈕常態(tài)與按下時(shí)的背景形狀可以完全不同行贪。有時(shí)候改變的不止是背景(包含形狀)、圖片派近,還可能是文字顏色。這些需求都可以通過(guò)selector標(biāo)簽來(lái)實(shí)現(xiàn)洁桌。

selector

selector可以有一個(gè)或者多個(gè)子標(biāo)簽item渴丸,而相應(yīng)的狀態(tài)是在item標(biāo)簽中定義的。定義的xml文件可以作為兩種資源使用:drawable和color另凌。作為drawable資源使用時(shí)谱轨,一般和shape一樣放于drawable目錄下,item必須指定android:drawable屬性吠谢;作為color資源使用時(shí)土童,則放于color目錄下,item必須指定android:color屬性工坊。

子標(biāo)簽的狀態(tài)屬性

  • android:state_enabled: 設(shè)置觸摸或點(diǎn)擊事件是否可用狀態(tài)献汗,一般只在false時(shí)設(shè)置該屬性,表示不可用狀態(tài)
  • android:state_pressed: 設(shè)置是否按壓狀態(tài)王污,一般在true時(shí)設(shè)置該屬性罢吃,表示已按壓狀態(tài),默認(rèn)為false
  • android:state_selected: 設(shè)置是否選中狀態(tài)昭齐,true表示已選中尿招,false表示未選中
  • android:state_checked: 設(shè)置是否勾選狀態(tài),主要用于CheckBox和RadioButton,true表示已被勾選就谜,false表示未被勾選
  • android:state_checkable: 設(shè)置勾選是否可用狀態(tài)怪蔑,類(lèi)似state_enabled,只是state_enabled會(huì)影響觸摸或點(diǎn)擊事件丧荐,而state_checkable影響勾選事件
  • android:state_focused: 設(shè)置是否獲得焦點(diǎn)狀態(tài)缆瓣,true表示獲得焦點(diǎn),默認(rèn)為false篮奄,表示未獲得焦點(diǎn)
  • android:state_window_focused: 設(shè)置當(dāng)前窗口是否獲得焦點(diǎn)狀態(tài)捆愁,true表示獲得焦點(diǎn)割去,false表示未獲得焦點(diǎn)窟却,例如拉下通知欄或彈出對(duì)話框時(shí),當(dāng)前界面就會(huì)失去焦點(diǎn)呻逆;另外夸赫,ListView的ListItem獲得焦點(diǎn)時(shí)也會(huì)觸發(fā)true狀態(tài),可以理解為當(dāng)前窗口就是ListItem本身
  • android:state_activated: 設(shè)置是否被激活狀態(tài)咖城,true表示被激活茬腿,false表示未激活,API Level 11及以上才支持宜雀,可通過(guò)代碼調(diào)用控件的setActivated(boolean)方法設(shè)置是否激活該控件
  • android:state_hovered: 設(shè)置是否鼠標(biāo)在上面滑動(dòng)的狀態(tài)切平,true表示鼠標(biāo)在上面滑動(dòng),默認(rèn)為false辐董,API Level 14及以上才支持
  • android:enterFadeDuration 狀態(tài)改變時(shí)悴品,新?tīng)顟B(tài)展示時(shí)的淡入時(shí)間,以毫秒為單位,API Level 11及以上
  • android:exitFadeDuration 狀態(tài)改變時(shí)简烘,舊狀態(tài)消失時(shí)的淡出時(shí)間苔严,以毫秒為單位,API Level 11及以上

控件的drawable XML:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 窗口失去焦點(diǎn)-->
    <item android:drawable="@drawable/bg_btn_lost_window_focused"
          android:state_window_focused="false"/>
    <!-- 不可用時(shí)-->
    <item android:drawable="@drawable/bg_btn_disabled"
          android:state_enabled="false"/>
    <!-- 按壓時(shí) -->
    <item android:drawable="@drawable/bg_btn_pressed"
          android:state_pressed="true"/>
    <!-- 被選中時(shí)-->
    <item android:drawable="@drawable/bg_btn_selected"
          android:state_selected="true"/>

    <!-- 被激活時(shí)-->
    <item android:drawable="@drawable/bg_btn_activated"
          android:state_activated="true"/>

    <!-- 獲取焦點(diǎn)時(shí)-->
    <item android:drawable="@drawable/bg_btn_focused"
          android:state_focused="true"/>

    <!-- 默認(rèn)狀態(tài)-->
    <item android:drawable="@drawable/bg_btn_normal" />

</selector>

字體的顏色XML:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 當(dāng)窗口失去焦點(diǎn)時(shí)的字體顏色-->
    <item android:color="@android:color/black"
          android:state_window_focused="false"/>
    <!-- 控件不可用時(shí)-->
    <item android:color="@android:color/background_light"
          android:state_enabled="false"/>
    <!-- 按壓時(shí)-->
    <item android:color="@android:color/holo_blue_light"
          android:state_pressed="true"/>
    <!-- 被選擇時(shí)-->
    <item android:color="@android:color/holo_orange_dark"
          android:state_selected="true"/>
    <!-- 被激活時(shí)-->
    <item android:color="@android:color/holo_red_dark"
          android:state_activated="true"/>
    <!-- 默認(rèn)時(shí)的字體顏色-->
    <item android:color="@android:color/black"/>
</selector>

在布局文件中的引用:

<Button
        android:id="@+id/activate_btn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="12dp"
        android:background="@drawable/bg_btn_selector"
        android:text="no activated"
        android:textColor="@color/text_btn_selector"/>

效果顯示如下:

StateListDrawable.gif

注意

  • selector作為drawable資源時(shí),item指定android:drawable屬性孤澎,并放于drawable目錄下届氢;
  • selector作為color資源時(shí),item指定android:color屬性覆旭,并放于color目錄下退子;
  • color資源也可以放于drawable目錄,引用時(shí)則用@drawable來(lái)引用型将,但不推薦這么做絮供,drawable資源和color資源最好還是分開(kāi);
  • android:drawable屬性除了引用@drawable資源茶敏,也可以引用@color顏色值壤靶;但android:color只能引用@color;
  • item是從上往下匹配的惊搏,如果匹配到一個(gè)item那它就將采用這個(gè)item贮乳,而不是采用最佳匹配的規(guī)則忧换;所以設(shè)置默認(rèn)的狀態(tài),一定要寫(xiě)在最后向拆,如果寫(xiě)在前面亚茬,則后面所有的item都不會(huì)起作用了。

ListView的Item樣式設(shè)置

有兩種設(shè)置方式浓恳,一種是在ListView標(biāo)簽里設(shè)置android:listSelector屬性刹缝,另一種是在ListItem的布局layout里設(shè)置android:background。兩者有很大的區(qū)別:

  • android:listSelector設(shè)置的ListItem默認(rèn)背景是透明的颈将,不管你在selector里怎么設(shè)置都無(wú)法改變它的背景梢夯。所以,如果想改ListItem的默認(rèn)背景晴圾,只能通過(guò)第二種方式颂砸,在ListItem的布局layout里設(shè)置android:background。
  • 當(dāng)觸摸點(diǎn)擊ListItem時(shí)死姚,第一種設(shè)置方式下人乓,state_pressed、state_focused和state_window_focused設(shè)為true時(shí)都會(huì)觸發(fā)都毒,而第二種設(shè)置方式下色罚,只有state_pressed會(huì)觸發(fā)。

如果你的自定義ListViewItem中有Button账劲、ImageButton或者Checkable的子類(lèi)控件的話戳护,那么默認(rèn)focus是交給了子控件,而ListView的Item能被選中的基礎(chǔ)是它能獲取Focus涤垫。所以常常當(dāng)點(diǎn)擊item時(shí)變化的是子控件姑尺,item本身的點(diǎn)擊沒(méi)有響應(yīng)。
解決方案:

  • 將Button或CheckBox換成TextView或ImageView之類(lèi)的控件
  • 設(shè)置Button或CheckBox之類(lèi)的控件設(shè)置focusable屬性為false
  • 設(shè)置ListItem的根布局屬性android:descendantFocusability="blocksDescendants"

第三種方法是最實(shí)用的蝠猬,descendantFocusability屬性可以設(shè)置一個(gè)控件如何處理觸摸事件切蟋,
該屬性是當(dāng)一個(gè)為view獲取焦點(diǎn)時(shí),定義viewGroup和其子控件兩者之間的關(guān)系榆芦。其值有:

  • beforeDescendants:ViewGroup會(huì)優(yōu)先其子類(lèi)控件而獲取到焦點(diǎn)
  • afterDescendants:ViewGroup只有當(dāng)其子類(lèi)控件不需要獲取焦點(diǎn)時(shí)才獲取焦點(diǎn)
  • blocksDescendants:ViewGroup會(huì)覆蓋子類(lèi)控件而直接獲得焦點(diǎn)

其原理是這樣一來(lái)ListItem的Layout(根View)就屏蔽了所有子控件獲取Focus的權(quán)限柄粹,如此就可以順利的響應(yīng)onItemClickListener中的onItenClick()方法了。

窗口焦點(diǎn)

這次實(shí)踐中涉及到了焦點(diǎn)問(wèn)題匆绣,自己測(cè)試了下驻右。發(fā)現(xiàn)問(wèn)題比較復(fù)雜,給自己留個(gè)作業(yè)崎淳,什么是窗口焦點(diǎn)堪夭,點(diǎn)擊控件會(huì)得到焦點(diǎn),幾個(gè)控件能同時(shí)得到焦點(diǎn)嗎,焦點(diǎn)和事件傳遞有關(guān)系嗎森爽?即使我采用上面的blocksDescendants屬性恨豁,發(fā)現(xiàn)ListView的item并沒(méi)有獲取到焦點(diǎn)(通過(guò)item.isFoucsed()來(lái)判斷),這是為什么爬迟?

View如何獲取焦點(diǎn)

Android新啟動(dòng)Activity橘蜜,dialog或者其他窗體中中包含EditText, 新啟動(dòng)的activity的焦點(diǎn)默認(rèn)在EditText上付呕,這是android系統(tǒng)會(huì)彈出軟鍵盤(pán)计福,擠壓activity本來(lái)的界面,影響美觀徽职。
因此最好在新窗體創(chuàng)建時(shí)象颖,最好在onCreate()方法中將焦點(diǎn)放在另一個(gè)view上. view使用requestFocus()焦點(diǎn),但是如果讓button或者textView之類(lèi)控件直接使用requestFocus()方法活箕,則無(wú)法獲取焦點(diǎn)力麸,焦點(diǎn)會(huì)依然在editText上可款。
只能在使用View的requestFocus()方法之前調(diào)用下面2個(gè)方法育韩,view才可獲取焦點(diǎn):

  1. view.setFocusable(true);
  2. view.setFocusableInTouchMode(true);
  3. 然后調(diào)用 requestFocus()即可獲取焦點(diǎn)。

遇到的問(wèn)題

  1. 通過(guò)selector標(biāo)簽定義的color資源與value目錄下的color.xml資源有什么區(qū)別闺鲸,有時(shí)間去看看color資源講解
  2. 導(dǎo)入項(xiàng)目筋讨,需要更改gradle-wapper文件的最后一項(xiàng)gradle版本,進(jìn)入項(xiàng)目后可能需要更改build.gradle(module:app)里面的buildToolVersion和build.gradle(Project:name)里面的gradle依賴版本摸恍。

參考

文獻(xiàn)悉罕、文獻(xiàn)2文獻(xiàn)3立镶、文獻(xiàn)4

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末壁袄,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子媚媒,更是在濱河造成了極大的恐慌嗜逻,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件缭召,死亡現(xiàn)場(chǎng)離奇詭異栈顷,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)嵌巷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)萄凤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人搪哪,你說(shuō)我怎么就攤上這事靡努。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵惑朦,是天一觀的道長(zhǎng)神年。 經(jīng)常有香客問(wèn)我,道長(zhǎng)行嗤,這世上最難降的妖魔是什么已日? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮栅屏,結(jié)果婚禮上飘千,老公的妹妹穿的比我還像新娘。我一直安慰自己栈雳,他們只是感情好护奈,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著哥纫,像睡著了一般霉旗。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蛀骇,一...
    開(kāi)封第一講書(shū)人閱讀 51,365評(píng)論 1 302
  • 那天厌秒,我揣著相機(jī)與錄音,去河邊找鬼擅憔。 笑死鸵闪,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的暑诸。 我是一名探鬼主播蚌讼,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼个榕!你這毒婦竟也來(lái)了篡石?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤西采,失蹤者是張志新(化名)和其女友劉穎凰萨,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體苛让,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡沟蔑,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了狱杰。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片瘦材。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖仿畸,靈堂內(nèi)的尸體忽然破棺而出食棕,到底是詐尸還是另有隱情朗和,我是刑警寧澤,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布簿晓,位于F島的核電站眶拉,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏憔儿。R本人自食惡果不足惜忆植,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望谒臼。 院中可真熱鬧朝刊,春花似錦、人聲如沸蜈缤。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)底哥。三九已至咙鞍,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間趾徽,已是汗流浹背续滋。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留附较,地道東北人吃粒。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓潦俺,卻偏偏與公主長(zhǎng)得像拒课,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子事示,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,111評(píng)論 25 707
  • 概述 今天我們來(lái)探究一下android的樣式早像。其實(shí),幾乎所有的控件都可以使用 background屬性去引用自定義...
    CokeNello閱讀 4,833評(píng)論 1 19
  • ¥開(kāi)啟¥ 【iAPP實(shí)現(xiàn)進(jìn)入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開(kāi)一個(gè)線程肖爵,因...
    小菜c閱讀 6,409評(píng)論 0 17
  • 你是否曾抱怨過(guò)產(chǎn)品經(jīng)理卢鹦,為什么一個(gè)app里面按鈕正常/按下?tīng)顟B(tài)顏色不統(tǒng)一起來(lái)?你是否曾埋怨過(guò)UI劝堪,為什么不同地方輸...
    chuwe1閱讀 2,702評(píng)論 2 28
  • 情不知所起秒啦,一往而情深熬粗。 想當(dāng)初第一次接觸排球的時(shí)候,就是為了某一個(gè)人余境,某些情驻呐。一種執(zhí)著囿于我的情感中灌诅,成了我高二...
    淺玖閱讀 405評(píng)論 0 1