Building an Android Settings Screen (Part 2)

How to Create and Fix the Dialogs

Jakob Ulbrich
5 min readMay 29, 2016
Fixing and Extending the android.support.v7.preference Library

In the first part of this tutorial we already built and themed our Settings Screen, the next step will be to fix the layout and the theme of the dialogs.

Because, technically, a preference dialog is a v7.app.AlertDialog, we can set their theme to Theme.AppCompat.DayNight.Dialog.Alert with the following entry in our Activity’s theme.

<item name="alertDialogTheme">
@style/Theme.AppCompat.DayNight.Dialog.Alert
</item>

This allows the dialogs to adapt their colors depending on if it’s day or night (You can find more information on how to use the DayNight theme here).

Default look of the preference dialogs

After applying the DayNight theme, our dialog should look like this and, as you can see, there are a lot of issues.

First of all, the text color of the dialog’s content is white on a white background.

The second thing is that the buttons are using the AppCompat’s default accentColor.

And the last issue is that the dialogMessage and the EditText do not have enough padding, so they are really close to the dialog’s edge and the title. Also the dialogMessage is straight below the title, which will definitely not look good, when we make the text visible.

I have enabled Show layout bounds in the developer options, so we can see the layout of all elements.

Fixing the Layout of the Dialog

When you take a look at the layout source code of the EditTextPreference’s dialog (You can find it here), you can see that the simply set the wrong padding for the content’s LinearLayout. They use android:padding=”5dip" which is not enough. Also the space between the dialogMessage and the EditText is set to 48dp which seems a lot to me. We better change this to another value.

We can find the proper values by looking at the v7.app.AlertDialog’s layout source code here. We can see that they use ?attr/dialogPreferredPadding as the left and right padding and a dimension abc_dialog_padding_top_material (18dp) as the top padding of the dialog.

Now we can create a new dimension resource with the currently discovered value of 18dp, because we will need this more than one time.

<dimen name="alert_def_padding">18dp</dimen>

After that, we copy us the whole dialog layout source code of the EditText preference from here to a new layout file called pref_dialog_edittext_fix.xml and change the paddings and margins.

<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>

We can apply the modified layout to our EditTextPreference in the xml/app_preferences.xml by adding the android:dialogLayout attribute.

<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" />

You can also add an remove Views from this custom layout, but always keep the EditText with the id @android:id/edit, because the v7.preference library will crash your App with an IllegalStateException if it can not find it. Also, fixing the layout for the ListPreference should be very similar.

The dialog after applying the layout fix

After digging through the layout source code, discovering the right dimensions and applying them to our EditTextPreference, everything in our dialog should now look perfectly aligned.

The title, the dialogMessage and EditText now have the same padding on the left and right. And we even increased the space between the title and the dialogMessage.

Fixing the Theme and Colors

We still have the wrong colors for the buttons and for the text in our dialog, which we are now going to fix. If you want to look at the AppCompat theme inheritance, you can find the source here.

Fixing the Color of the Buttons

The dialog before and after changing colorAccent in the dialogs’s theme

Our dialog’s theme does override colorAccent from our Acivity’s theme with the default greenish color which is provided in the DayNight.Dialog.Alert theme.

This is the reason why the dialog buttons do not use colorAccent from our Activity’s theme.

If we want to change the button color, we need to modify our dialog’s theme.

We do this with the following in our styles.xml. First we create a new style called AppAlertDialog, which inherits from our previous dialog’s theme. In this new style, we can modify our colorAccent as we want to. After that, we say our Activity’s theme to use our newly created style as the alertDialogTheme.

<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>

Fixing the Color of the Text

The dialog before and after changing the theme of the content

Since our Activity’s theme is Theme.AppCompat, which provides white text, and our our dialog’s theme does not override this, we also get white text in our dialog.

We could override all text colors in our dialog’s theme by our own, but this would require a lot of work. And if we are using the DayNight theme, it is even harder.

So the easiest way is to apply the theme to a Layout that includes the content elements of our dialog.

First we create a new style, which inherits from a theme that we want to use. In this case it is Theme.AppCompat.DayNight, because we want that the color of the text also adapts depending on if it is day or night. If we would not use the DayNight theme, it could result in dark text on a dark background at night. When we later apply this style as our dialog’s content theme, it does not inherit the colorAccent from our Activity’s theme anymore. That’s why we have to add it to this style again, to keep the current color of the EditText.

<style name="AppAlertDialogContent"
parent="Theme.AppCompat.DayNight">
<!-- To keep the color of EditText -->
<item name="colorAccent">@color/colorAccent</item>
</style>

Now we go back to the pref_dialog_edittext_fix.xml file, which we created to fix the layout issues of the EditTextPreference, search for the root Layout and add our theme there.

<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">

You can change your dialog’s content theme as you want.

When we now open our dialog, you should not be able to find any layout or theme issues anymore. But if you do, you should be able to solve them by modifying the layout file or one of our recently created styles.

This was the second step to create a material design Settings Screen. The next part of this tutorial will be about how to build custom preferences and how to solve the design issues which occur during this process.

The third Part of this tutorial series is available below.

You can have a look at the project files on GitHub.

Thanks for reading and happy coding 💻.

--

--