首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Android 代碼動態修改 Selector (StateListDrawable) 單態圖片:重建替換而非修改現有對象

     編輯:程式設計綜合問答

需求:ImageView 背景為 Selector (XML 定義),運行時需根據條件替換 state_pressed、state_focused、default 三種狀態的圖片。

限制:StateListDrawable 不支持運行時修改單個 State

一旦 XML 膨脹為 StateListDrawable,**內部狀態映射表不可變**,無 setStateDrawable() 等方法。

解決方案:代碼構建新 StateListDrawable 並設置

public void updateImageViewStates(ImageView imageView, 
                                  int normalRes, int pressedRes, int focusedRes) {
    
    StateListDrawable states = new StateListDrawable();
    
    // 順序很重要:優先匹配具體狀態,最後默認
    states.addState(new int[]{android.R.attr.state_pressed}, 
        ContextCompat.getDrawable(imageView.getContext(), pressedRes));
    states.addState(new int[]{android.R.attr.state_focused}, 
        ContextCompat.getDrawable(imageView.getContext(), focusedRes));
    states.addState(new int[]{}, // 空數組 = 默認狀態
        ContextCompat.getDrawable(imageView.getContext(), normalRes));
    
    imageView.setImageDrawable(states); // 或 setBackgroundDrawable
}

調用示例

updateImageViewStates(myImageView, 
    R.drawable.btn_normal_new, 
    R.drawable.btn_pressed_new, 
    R.drawable.btn_focused_new);

進階:保留原有 Selector 結構,僅替換部分狀態

若原 Selector 來自 XML 且結構複雜,需解析現有 StateListDrawable 獲取所有 State Spec,再重建:

// 注意:StateListDrawable 無公開 API 遍歷 states,需反射或複製邏輯
// 實際建議:直接按新需求全量重建,避免反射脆弱性

性能提示

  • 頻繁調用時**緩存 StateListDrawable 實例**,避免重複創建 Drawable 對象。
  • 使用 Drawable.ConstantState.newDrawable() 複製共享常量狀態。

現代替代:AnimatedStateListDrawable (API 24+)

支持狀態轉場動畫,XML 定義 <animated-selector>,代碼動態構建同理。

理解 Selector 不可變性,採用「重建替換」模式動態控制狀態圖片。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved