Android,android官網

來源:互聯網
上載者:User

Android,android官網
selector                                                                               

<?xml version="1.0" encoding="utf-8" ?>     <selector xmlns:android="http://schemas.android.com/apk/res/android">     <!-- 觸摸時並且當前視窗處於互動狀態 -->      <item android:state_pressed="true" android:state_window_focused="true" android:drawable= "@drawable/pic1" />    <!--  觸摸時並且沒有獲得焦點狀態 -->      <item android:state_pressed="true" android:state_focused="false" android:drawable="@drawable/pic2" />      <!--選中時的圖片背景-->      <item android:state_selected="true" android:drawable="@drawable/pic3" />       <!--獲得焦點時的圖片背景-->      <item android:state_focused="true" android:drawable="@drawable/pic4" />      <!-- 視窗沒有處於互動時的背景圖片 -->      <item android:drawable="@drawable/pic5" />   </selector>
StateListDrawable                                                                   

該類定義了不同狀態值下與之對應的圖片資源,即我們可以利用該類儲存多種狀態值,多種圖片資源。

public void addState (int[] stateSet, Drawable drawable)

給特定的狀態集合設定drawable圖片資源,參考前面的selector的xml檔案,我們利用代碼去構建一個相同的StateListDrawable類對象

//初始化一個Null 物件  StateListDrawable stalistDrawable = new StateListDrawable();  //擷取對應的屬性值 Android架構內建的屬性 attr  int pressed = android.R.attr.state_pressed;  int window_focused = android.R.attr.state_window_focused;  int focused = android.R.attr.state_focused;  int selected = android.R.attr.state_selected;    stalistDrawable.addState(new int []{pressed , window_focused}, getResources().getDrawable(R.drawable.pic1));  stalistDrawable.addState(new int []{pressed , -focused}, getResources().getDrawable(R.drawable.pic2);  stalistDrawable.addState(new int []{selected }, getResources().getDrawable(R.drawable.pic3);  stalistDrawable.addState(new int []{focused }, getResources().getDrawable(R.drawable.pic4);  //沒有任何狀態時顯示的圖片,我們給它設定我空集合  stalistDrawable.addState(new int []{}, getResources().getDrawable(R.drawable.pic5);

上面的“-”負號表示對應的屬性值為false

public boolean isStateful ()

表明該狀態改變了,對應的drawable圖片是否會改變。(在StateListDrawable類中,該方法返回為true,顯然狀態改變後,我們的圖片會跟著改變。)

狀態                                                                                   

android:state_selected 選中
android:state_focused 獲得焦點
android:state_pressed 點擊
android:state_enabled 設定是否響應事件,指所有事件

selected和focused的區別                                                            
  • focused狀態一般是由按鍵動作引起的;
  • pressed狀態是由觸摸訊息引起的;
  • selected則完全是由應用程式主動調用setSelected()進行控制。
分析                                                                                   

當View任何狀態值發生改變時,都會調用refreshDrawableList()方法去更新對應的背景Drawable對象。

//主要功能是根據當前的狀態值去更換對應的背景Drawable對象      public void refreshDrawableState() {          mPrivateFlags |= DRAWABLE_STATE_DIRTY;          //所有功能在這個函數裡去完成          drawableStateChanged();          //...      }      // 獲得當前的狀態屬性--- 整型集合 ; 調用Drawable類的setState方法去擷取資源。      protected void drawableStateChanged() {          //該視圖對應的Drawable對象,通常對應於StateListDrawable類對象          Drawable d = mBGDrawable;             if (d != null && d.isStateful()) {  //通常都是成立的              //getDrawableState()方法主要功能:會根據當前View的狀態屬性值,將其轉換為一個整型集合              //setState()方法主要功能:根據當前的擷取到的狀態,更新對應狀態下的Drawable對象。              d.setState(getDrawableState());          }      }      public final int[] getDrawableState() {          if ((mDrawableState != null) && ((mPrivateFlags & DRAWABLE_STATE_DIRTY) == 0)) {              return mDrawableState;          } else {              //根據當前View的狀態屬性值,將其轉換為一個整型集合,並返回              mDrawableState = onCreateDrawableState(0);              mPrivateFlags &= ~DRAWABLE_STATE_DIRTY;              return mDrawableState;          }      }

setState()

//如果狀態態值發生了改變,就回調onStateChange()方法。  public boolean setState(final int[] stateSet) {      if (!Arrays.equals(mStateSet, stateSet)) {          mStateSet = stateSet;          return onStateChange(stateSet);      }      return false;  }

判斷狀態值是否發生了變化,如果發生了變化,就調用onStateChange()方法進一步處理。

//狀態值發生了改變,我們需要找出第一個吻合的目前狀態的Drawable對象  protected boolean onStateChange(int[] stateSet) {      //要找出第一個吻合的目前狀態的Drawable對象所在的索引位置, 具體匹配演算法請自己深入源碼看看      int idx = mStateListState.indexOfStateSet(stateSet);      ...      //擷取對應索引位置的Drawable對象      if (selectDrawable(idx)) {          return true;      }      ...  }

根據新的狀態值,從StateListDrawable執行個體對象中,找到第一個完全吻合該新狀態值的索引下標處 ; 繼而,調用selectDrawable()方法去擷取索引下標的當前Drawable對象。

public boolean selectDrawable(int idx)  {      if (idx >= 0 && idx < mDrawableContainerState.mNumChildren) {          //擷取對應索引位置的Drawable對象          Drawable d = mDrawableContainerState.mDrawables[idx];          ...          mCurrDrawable = d; //mCurrDrawable即使當前Drawable對象          mCurIndex = idx;          ...      } else {         ...      }      //請求該View重新整理自己,這個方法我們稍後講解。      invalidateSelf();      return true;  }
Drawable.Callback                                                                    
public static interface Callback {      //如果Drawable對象的狀態發生了變化,會請求View重新繪製,      //因此我們對應於該View的背景Drawable對象能夠”繪製出來”.      public void invalidateDrawable(Drawable who);      public void scheduleDrawable(Drawable who, Runnable what, long when);       public void unscheduleDrawable(Drawable who, Runnable what);  }

Android架構View類繼承了該介面,同時實現了這三個函數的預設處理方式,其中invalidateDrawable()方法如下:

public class View implements Drawable.Callback, KeyEvent.Callback, AccessibilityEventSource   {      ...      //Invalidates the specified Drawable.      //預設實現,重新繪製該視圖本身      public void invalidateDrawable(Drawable drawable) {          if (verifyDrawable(drawable)) { //是否是同一個Drawable對象,通常為真              final Rect dirty = drawable.getBounds();              final int scrollX = mScrollX;              final int scrollY = mScrollY;              //重新請求繪製該View,即重新調用該View的draw()方法  ...              invalidate(dirty.left + scrollX, dirty.top + scrollY,                      dirty.right + scrollX, dirty.bottom + scrollY);          }      }      ...  }

因此,我們的Drawable類對象必須將View設定為回調對象,否則,即使改變了狀態,也不會顯示對應的背景圖。

Drawable d  ;                // 圖片資源                        d.setCallback(View v) ;  // 視圖v的背景資源為 d 對象
我是天王蓋地虎的分割線                                                             

 

 

參考:http://blog.csdn.net/qinjuning/article/details/7474827

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.