
彈出對話框?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等分別控制什么的顏色呢。別著急,先看下面一張圖:

- android:colorPrimaryDark 應(yīng)用的主要暗色調(diào),statusBarColor默認使用該顏色
- android:statusBarColor 狀態(tài)欄顏色,默認使用colorPrimaryDark
- android:colorPrimary 應(yīng)用的主要色調(diào),actionBar默認使用該顏色
- android:windowBackground 窗口背景顏色
- android:navigationBarColor 底部欄顏色
- android:colorForeground 應(yīng)用的前景色,ListView的分割線,switch滑動區(qū)默認使用該顏色
- android:colorBackground 應(yīng)用的背景色,popMenu的背景默認使用該顏色
- android:colorAccent 一般控件的選種效果默認采用該顏色
- android:colorControlNormal 控件的默認色調(diào)
- android:colorControlHighlight 控件按壓時的色調(diào)
- android:colorControlActivated 控件選中時的顏色,默認使用colorAccent
- android:colorButtonNormal 默認按鈕的背景顏色
- android:textColor Button,textView的文字顏色
- android:textColorPrimaryDisableOnly RadioButton checkbox等控件的文字
- 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>
運行看看效果吧:

哇~ 終于改成和狀態(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。
