创建 Android 设置界面 (第二部分)
在第一部分中我们创建了一个Settings界面并为之设置了主题,接下来我们将修复对话框布局和主题存在的问题。
点击EditTextPreference就会打开dialog。
因为从技术上说preference dialog其实就是 v7.app.AlertDialog,我们可以在 Activity的theme中用下面的入口把它的主题设置为Theme.AppCompat.DayNight.Dialog.Alert。
<item name="alertDialogTheme">
@style/Theme.AppCompat.DayNight.Dialog.Alert
</item>
这个样式可以让dialog根据是否为日间或者夜间主题采用相应的颜色(关于如何设置DayNight主题,可以参考这里)。
当我们应用了DayNight theme之后,对话框是这个样子的,可以看到存在很多问题。
首先,dialog内容文字的颜色是白色的,且在一个白色的背景上。
其次,按钮使用了AppCompat默认的accentColor,而不是我们在主题中设置的accentColor。
最后一个问题是dialogMessage以及EditText没有足够的padding,离dialog的边界和标题太近。dialogMessage也是紧挨着标题,这看起来绝对不爽(这里文字是白色的看不出来)。
我在开发者选项中开启了显示布局边界,因此你可以看到所有元素的布局。
修复Dialog的布局
当你看了EditTextPreference的布局源码 (可以在这里找到)之后,可以看到他们为内容的LinearLayout应用了错误的padding。他们使用的是 android:padding=”5dip",这显然是不够的。而dialogMessage与EditText的距离设置为48dp,对我而言这太大了,我们最好把它值设置为其它的值。
正确的值我们可以参考 这里 的v7.app.AlertDialog的布局源码。可以看到左右padding用的是?attr/dialogPreferredPadding ,顶部padding用的是dimension abc_dialog_padding_top_material (18dp) 。
现在我们可以新建一个dimension资源,把它设置为18dp,以方便后面使用。
<dimen name="alert_def_padding">18dp</dimen>
完了之后我们从这里把EditText preference对话框的整个布局源码拷贝到一个新的布局 pref_dialog_edittext_fix.xml,然后修改padding和margin。
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="48dp"
android:layout_marginBottom="48dp"
android:overScrollMode="ifContentScrolls">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/alert_def_padding"
android:paddingBottom="@dimen/alert_def_padding"
android:paddingStart="?dialogPreferredPadding"
android:paddingLeft="?dialogPreferredPadding"
android:paddingEnd="?dialogPreferredPadding"
android:paddingRight="?dialogPreferredPadding"
android:orientation="vertical">
<TextView
android:id="@android:id/message"
style="?android:attr/textAppearanceSmall"
android:layout_marginBottom="@dimen/alert_def_padding"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="?android:attr/textColorSecondary" />
<EditText
android:id="@android:id/edit"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</ScrollView>
我们可以为EditTextPreference添加android:dialogLayout 属性来改变对话框的布局:
<android.support.v7.preference.EditTextPreference
android:key="key2"
android:title="EditText Preference"
android:summary="EditText Summary"
android:dialogMessage="Dialog Message"
android:defaultValue="Default value"
android:dialogLayout="@layout/pref_dialog_edittext_fix" />
当然你可以往这个自定义布局中添加或者删除view,但要保证EditText的id为@android:id/edit,因为如果v7.preference library找不到它就会引起App的崩溃。同样,修复ListPreference对话框的布局也可以采用相同的方式。
现在对话框的对齐和padding看起来都很完美了。
修复 Theme 和 Color
现在dialog中的按钮和文字的颜色仍然是不对的,我们来修复它。如果你想看看 AppCompat theme继承关系,你可以在 这里 找到源码。
修复按钮颜色
---在dialog主题中修改colorAccent前后的dialog
我们的dialog主题使用 DayNight.Dialog.Alert theme提供给的默认浅绿色覆盖了Acivity主题中设置的colorAccent,这就是为什么dialog的按钮没有使用Activity主题的colorAccent的原因。
如果我们想改变按钮颜色,我们需要修改dialog的主题。
为此我们在 styles.xml文件中使用下面的代码。首先新建一个名为AppAlertDialog的style,让它继承前面我们提到的dialog主题(DayNight.Dialog.Alert)。这样我们就可以把colorAccent改为我们想要的颜色。然后把Activity主题的alertDialogTheme设置为新创建的style。
<style name="AppTheme" parent="Theme.AppCompat">
<!-- ... other stuff ... -->
<item name="preferenceTheme">
@style/PreferenceThemeOverlay.v14.Material
</item>
<item name="alertDialogTheme">@style/AppAlertDialog</item>
</style>
<style name="AppAlertDialog"
parent="Theme.AppCompat.DayNight.Dialog.Alert">
<item name="colorAccent">@color/colorAccent</item>
</style>
修复文字颜色
---修改内容布局主题前后的dialog
因为Activity的主题是 Theme.AppCompat,它的文字颜色是白色,而dialog主题没有覆盖这个颜色,所以在dialog中文字也为白色。我们可以在dialog主题中覆盖所有文字颜色,但这需要相当的工作量。而如果我们使用DayNight主题,工作量更大。
所以最简单的办法是对dialog的内容布局应用主题。
首先新建一个style,让它继承一个我们想要的主题。因为我们想让文字颜色做到根据是否为日间或者夜间主题自适应,所以这里我们让它继承Theme.AppCompat.DayNight。如果不使用DayNight主题,在夜间主题的时候可能会出现深色文字在深色背景上。但是Theme.AppCompat.DayNight主题不再继承Activity主题的colorAccent,所以这里还得再次添加colorAccent,让EditText保持目前的颜色。
<style name="AppAlertDialogContent"
parent="Theme.AppCompat.DayNight">
<!-- To keep the color of EditText -->
<item name="colorAccent">@color/colorAccent</item>
</style>
现在回到pref_dialog_edittext_fix.xml文件,在它的根布局上添加我们创建的主题。
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="48dp"
android:layout_marginBottom="48dp"
android:overScrollMode="ifContentScrolls"
android:theme="@style/AppAlertDialogContent">
现在打开dialog,应该不再有任何问题了。如果还有问题,你也应该知道如何修改我们创建的样式和布局来解决了。
这是创建material design设置界面的第二步。下一部分我们将是关于如何自定义preferences以及如何解决这个过程中出现的问题。
第三部分见:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2017/0721/8221.html
项目代码见 GitHub。
感谢阅读,祝编码愉快!