通過源碼分析,修改AlertDialog按鈕的顏色

對話框

彈出對話框?qū)θ魏我粋€Android開發(fā)者都不是什么難事,代碼也非常簡單,簡單的貼出來都覺得是個不光彩的事。

    public void showDialog(View v){
        AlertDialog.Builder builder=new AlertDialog.Builder(this);
        builder.setTitle("dialog");
        builder.setPositiveButton("確定", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                // .....
            }
        });
        builder.setNegativeButton("取消",null);
        builder.show();
    }

如果這是一個普通的AlertDialog教程,寫到此處就大功告成了。問題是,公司產(chǎn)品經(jīng)理感覺Dialog按鈕的顏色不舒服,和綠帽子一樣顏色,太不爽,想改成和頂部AppBar一個顏色。
我想了想,覺得因為一個Dialog跳槽走人也說不過去,只能拍拍胸脯說沒問題。

眾所周知,我們可以setView()定制不同界面樣式的Dialog,隨便你在布局中發(fā)揮

        AlertDialog.Builder builder=new AlertDialog.Builder(this);
        builder.setView(view);
        builder.show();

但是這種方法還要去搭建一個布局文件,太不爽。
緊接著我突然想到了,通過修改Dialog主題樣式從而改變Dialog按鈕的顏色。天才啊~
直接打開主題樣式文件 values\styles.xml。

<resources>

    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

</resources>

當(dāng)前程序采用的是AppCompat的主題,也是目前程序主流的主題。
然,并,卵!
如何修改Dialog樣式了呢。上面的colorPrimary,colorAccent等分別控制什么的顏色呢。別著急,先看下面一張圖:

主題顏色
  1. android:colorPrimaryDark 應(yīng)用的主要暗色調(diào),statusBarColor默認使用該顏色
  2. android:statusBarColor 狀態(tài)欄顏色,默認使用colorPrimaryDark
  3. android:colorPrimary 應(yīng)用的主要色調(diào),actionBar默認使用該顏色
  4. android:windowBackground 窗口背景顏色
  5. android:navigationBarColor 底部欄顏色
  6. android:colorForeground 應(yīng)用的前景色,ListView的分割線,switch滑動區(qū)默認使用該顏色
  7. android:colorBackground 應(yīng)用的背景色,popMenu的背景默認使用該顏色
  8. android:colorAccent 一般控件的選種效果默認采用該顏色
  9. android:colorControlNormal 控件的默認色調(diào)
  10. android:colorControlHighlight 控件按壓時的色調(diào)
  11. android:colorControlActivated 控件選中時的顏色,默認使用colorAccent
  12. android:colorButtonNormal 默認按鈕的背景顏色
  13. android:textColor Button,textView的文字顏色
  14. android:textColorPrimaryDisableOnly RadioButton checkbox等控件的文字
  15. android:textColorPrimary 應(yīng)用的主要文字顏色,actionBar的標題文字默認使用該顏色

上面加粗的就是創(chuàng)建項目默認帶的,哇~ 原來主題可以控制這么多顏色啊。其實這還不是全部的啊。
問題回到主題,如何修改AlertDialog按鈕的顏色啊。上面沒有寫著啊。不要怕,咱們?nèi)タ纯碅lertDialog的源碼。
AlertDialog是通過Builder創(chuàng)建的。

        public Builder(Context context) {
            this(context, resolveDialogTheme(context, 0));
        }

可以看到片Build創(chuàng)建的時候調(diào)用了resolveDialogTheme這個方法,英語好的一眼就知道這是解析主題的意思,點進去看看這個方法:

    static int resolveDialogTheme(Context context, int resid) {
        if (resid >= 0x01000000) {   // start of real resource IDs.
            return resid;
        } else {
            TypedValue outValue = new TypedValue();
            context.getTheme().resolveAttribute(R.attr.alertDialogTheme, outValue, true);
            return outValue.resourceId;
        }
    }

*** 核心是看這個:context.getTheme().resolveAttribute(R.attr.alertDialogTheme, outValue, true);***
這個話的意思就是上下文獲取當(dāng)前主題解析alertDialogTheme這個屬性。
原來終于明白了,我們要想修改AlertDialog樣式需要在主題中設(shè)置alertDialogTheme,這個屬性。

    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <item name="alertDialogTheme">怎么寫啊??</item>
    </style>

問題來了,alertDialogTheme這個又該怎么寫呢。這次ctrl+左鍵點擊Theme.AppCompat.Light.DarkActionBar進去看看默認的alertDialogTheme是怎么配置的,我們按照葫蘆畫瓢就可以了。
進來千萬不要頭暈,我們來縷縷:
首先

<style name="Theme.AppCompat.Light.DarkActionBar" parent="Base.Theme.AppCompat.Light.DarkActionBar"/>

繼續(xù)翻家譜,點擊父樣式Base.Theme.AppCompat.Light.DarkActionBar

    <style name="Base.Theme.AppCompat.Light.DarkActionBar" parent="Base.Theme.AppCompat.Light">
        <item name="actionBarPopupTheme">@style/ThemeOverlay.AppCompat.Light</item>
        <item name="actionBarWidgetTheme">@null</item>
        <item name="actionBarTheme">@style/ThemeOverlay.AppCompat.Dark.ActionBar</item>

        <!-- Panel attributes -->
        <item name="listChoiceBackgroundIndicator">@drawable/abc_list_selector_holo_dark</item>

        <item name="colorPrimaryDark">@color/primary_dark_material_dark</item>
        <item name="colorPrimary">@color/primary_material_dark</item>
    </style>

發(fā)現(xiàn)Base.Theme.AppCompat.Light.DarkActionBar還是沒有我們想要的,繼續(xù)點擊Base.Theme.AppCompat.Light,繼續(xù)往上翻

<style name="Base.Theme.AppCompat.Light" parent="Base.V7.Theme.AppCompat.Light"></style>

繼續(xù)...

<style name="Base.V7.Theme.AppCompat.Light" parent="Platform.AppCompat.Light">
    ....
   <item name="alertDialogTheme">@style/Theme.AppCompat.Light.Dialog.Alert</item>
</style>

終于功夫不負有心人,找到了alertDialogTheme這個屬性,看看它對應(yīng)的是@style/Theme.AppCompat.Light.Dialog.Alert
我們把這個代碼復(fù)制到我們的樣式中,這就相當(dāng)于你什么都沒改:

    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <item name="alertDialogTheme">@style/Theme.AppCompat.Light.Dialog.Alert</item>
    </style>

于是乎我們開始自定義這個樣式Theme.AppCompat.Light.Dialog.Alert

    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <item name="alertDialogTheme">@style/Theme.AppCompat.Light.Dialog.Alert.Self</item>
    </style>

    <style name="Theme.AppCompat.Light.Dialog.Alert.Self"
           parent="@style/Theme.AppCompat.Light.Dialog.Alert">
          <!--怎么寫呢?-->
    </style>

怎么自定義呢,于是乎,又需要翻看Theme.AppCompat.Light.Dialog.Alert的源碼了。過程和上面雷同,需要多翻幾次,就不列舉了。直接說結(jié)果,最終你會發(fā)現(xiàn)
Theme.AppCompat.Light.Dialog.Alert繼承自Base.V7.Theme.AppCompat.Light

<style name="Base.V7.Theme.AppCompat.Light" parent="Platform.AppCompat.Light">
    ....
  
</style>

這個是不是很眼熟啊,沒錯,上面的代碼曾經(jīng)翻到過它。這時候如果你按照正常思維模式去查看哪個屬性控制按鈕顏色,你還需要翻看AlerDialog源碼,我只能說有點麻煩了,很不爽的。
那怎么看呢?
介紹一個小技巧。
我們先看按鈕默認的顏色。

按鈕顏色

然后看Base.V7.Theme.AppCompat.Light樣式下只有colorAccent 對應(yīng)這個顏色。

按鈕顏色

于是乎我們可以猜測,colorAccent 這個屬性可能是控制按鈕的顏色。于是乎趕快添加到自定義的樣式中。填寫和狀態(tài)欄的一樣的顏色:

    <style name="Theme.AppCompat.Light.Dialog.Alert.Self"
           parent="@style/Theme.AppCompat.Light.Dialog.Alert">
        <item name="colorAccent">#3F51B5</item>
    </style>

運行看看效果吧:

Paste_Image.png

哇~ 終于改成和狀態(tài)欄一個顏色了。
把最終代碼粘貼出來,僅僅是改了values/styles中的主題樣式:

    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <!--自定義AlertDialog-->
        <item name="alertDialogTheme">@style/Theme.AppCompat.Light.Dialog.Alert.Self</item>
    </style>
    <style name="Theme.AppCompat.Light.Dialog.Alert.Self"
           parent="@style/Theme.AppCompat.Light.Dialog.Alert">
        <!--修改AlertDialog按鈕的顏色-->
        <item name="colorAccent">#3F51B5</item>
    </style>
</resources>

雖然,過程很復(fù)雜,但是結(jié)果確很簡單。開發(fā)是非常重視結(jié)果的,但學(xué)習(xí)的時候過程的體驗還是必不可少的,通過學(xué)習(xí)這個分析過程,大家可以嘗試修改其它控件默認的樣式啦。
更多精彩請關(guān)注微信公眾賬號likeDev,公眾賬號名稱:愛上Android。

likeDev.jpg
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容