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

Android Button 狀態圖片 Selector 封裝:自定義屬性實現複用避免重複 XML

     編輯:程式設計綜合問答

痛點

每個 Button 都需寫 selector XML (btn_background.xml),項目中按鈕眾多時極其繁瑣,維護成本高。

解決方案:自定義 Button 組件 + 自定義屬性

1. 定義自定義屬性




    
    
    
    

2. 實現自定義 Button


public class StateButton extends AppCompatButton {
    private Drawable normalDrawable, pressedDrawable, focusedDrawable, disabledDrawable;
    private StateListDrawable stateListDrawable;

    public StateButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }

    private void init(Context context, AttributeSet attrs) {
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.StateButton);
        normalDrawable = a.getDrawable(R.styleable.StateButton_normalDrawable);
        pressedDrawable = a.getDrawable(R.styleable.StateButton_pressedDrawable);
        focusedDrawable = a.getDrawable(R.styleable.StateButton_focusedDrawable);
        disabledDrawable = a.getDrawable(R.styleable.StateButton_disabledDrawable);
        a.recycle();

        buildStateListDrawable();
        setBackground(stateListDrawable); // 背景而非 src
    }

    private void buildStateListDrawable() {
        stateListDrawable = new StateListDrawable();
        // 順序重要:具體狀態在前,默認在後
        if (pressedDrawable != null) 
            stateListDrawable.addState(new int[]{android.R.attr.state_pressed}, pressedDrawable);
        if (focusedDrawable != null) 
            stateListDrawable.addState(new int[]{android.R.attr.state_focused}, focusedDrawable);
        if (disabledDrawable != null) 
            stateListDrawable.addState(new int[]{-android.R.attr.state_enabled}, disabledDrawable);
        if (normalDrawable != null) 
            stateListDrawable.addState(StateSet.WILD_CARD, normalDrawable); // 默認
    }

    // 運行時動態修改
    public void setNormalDrawable(Drawable d) {
        normalDrawable = d;
        buildStateListDrawable();
    }
    // ... 其他 setter
}

3. 佈局中直接使用



進階:統一風格主題屬性 (更優雅)










    
    
    
    

所有 Button 自動套用主題風格,單個覆蓋只需在佈局加 style="@style/Widget.App.Button.Secondary"。

現代方案:MaterialButton (Material Components)



優勢:內建 Ripple、ShapeAppearance、狀態屬性映射、無需自定義類、符合 Material Design 規範。

方案對比總結

方案優點缺點推薦場景
每個 Button 寫 selector完全可控重複代碼、維護地獄極少量特殊按鈕
自定義 StateButton + 屬性佈局簡潔、運行時可改、邏輯集中需維護自定義類中型專案、需動態換膚
主題統一 buttonStyle全局一致、零佈局侵入、易換膚靈活性稍低規範化團隊、標準化 UI 庫
MaterialButton現代、功能豐富、官方維護、無樣板代碼需依賴 material 库所有新專案首選
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved