How to style AlertDialogs like a pro

In the previous blog post, I tried to clarify what Android styles and themes are and how you can easily customise your app. So, now you’re an expert. You’ve spent hours playing with fonts, colors, margins, sizes, animations, etc. and you handle resource and drawable files like nobody else.

But if you’ve ever tried to make an AlertDialog to fit your exact wishes, you know how hard it is. Under the appearances, an AlertDialog is not that simple. This AlertDialog styling issue is nothing but the actual reason of why I wrote these two blog posts. I tried and tried over, and in the process I’ve learnt so much. Did I succeed? Well, not entirely, let me share my discoveries with you. Most tutorials we find on the Internet about customising AlertDialogs actually talk about using a totally custom view, but then you lose the whole genericity, simplicity and reusability of the AlertDialog: this is not the subject of this post.

This blog post is partly inspired by the very good work of Jörg Richter: http://joerg-richter.fuyosoft.com/?p=181

What is an AlertDialog?

It is a little window that appears in the UI to warn the users or to request a choice from them. For example, delete a contact, download a file, add a word to a dictionary… These are the cases where you can use Dialogs.

Example of AlertDialogs

Example of AlertDialogs (from Android UI Guide)

In the Android framework, AlertDialog is in fact a child of the Dialog class. Dialog is very generic: this is the base class for, say, all kinds of components that have this “overlay” behaviour. For example, when long-pressing on a character on your keyboard, the little box you get with accented characters is a Dialog: CharacterPickerDialog.

But our focus here is the AlertDialog class. It generally has a title, a message, and up to three buttons. It can also display a list of items, or have a completely custom layout. To create an AlertDialog, you have to use a Builder object that will handle the creation process for you.

As for styling, a theme can specify two attributes related to AlertDialogs: alertDialogTheme and alertDialogStyle (we’ll dive into that soon enough). You can also specify the style of an AlertDialog when you create the Builder:

  • With a predefined constant referencing the theme:
    The AlertDialog class has a few predefined constants:

    • THEME_DEVICE_DEFAULT_DARK
    • THEME_DEVICE_DEFAULT_LIGHT
    • THEME_HOLO_DARK
    • THEME_HOLO_LIGHT
    • THEME_TRADITIONAL
  • If you want to apply to your AlertDialog a theme different than the one specified in your Activity’s theme, you can use a ContextThemeWrapper around your current context:
Difference between DeviceDefault dark/light, Holo dark/light and Traditional (Nexus 5, Android L)

Difference between DeviceDefault dark/light, Holo dark/light and Traditional (Nexus 5, Android L)

You already have 5 options to customise your AlertDialog if you use the predefined themes. But how can you define your own dialog appearance?

Set up a simple example

We’ll start with a very simple example. One app, one single activity, one button in the middle that opens an AlertDialog. We’ll base our theme on Holo and then customise it. Here’s our MainActivity:

 

In accordance to my advice in the previous blog post, we have of course created a xml for our theme(s), sphinx_themes.xml.

And one for our styles, sphinx_styles.xml.

 

For now, our custom theme Sphinx.Theme only defines an orange ActionBar in the Activity, and all the rest is inherited from Theme.Holo. Our AlertDialog.Builder is created without a second parameter, so the AlertDialog will look like defined in the theme. That’s what we have:

Test app base

Now we want to start editing our own theme for the AlertDialog based on Holo. We learn from Android source (themes.xml) that the base AlertDialog theme is Theme.Holo.Dialog.Alert, but it is private! No worries, we can copy the source code from the same link to “recreate” this default theme. If we copy only Theme.Holo.Dialog.Alert we’ll get an error, because DialogWindowTitle.Holo is also a private style. We do the same trick here: copy it from the source. The result is:

And this can now be used as a base for our custom AlertDialog theme:

 

Style the dialog

Part 1

Part 1: style the title

I want my title green, bold and condensed.

We need to override the windowTitleStyle attribute of the theme, and in this, override the textAppearance.
In sphinx_themes.xml,

In sphinx_styles.xml,

 

Yeah!

Part 2

Part 2: style the message

I want my message smaller, orange and italic.

If the title has its own style (windowTitleStyle), easy to customise, for the message it’s a little bit different because it relies on the concept of textApperance. Which means:

  • We should define the color of the message as a theme attribute, namely textColorPrimary.
  • We should define the size/style of the message in the TextAppearance style, knowing that it uses a medium TextAppearance.

We need to add: in sphinx_themes.xml,

In sphinx_styles.xml,

Woohoo!

But you’ll notice that our buttons are also affected by the italic appearance. That’s because they use the medium text appearance as well, just like many widgets by the way. We’ll see how to change that in the next part.
Also, you may use a dialog to display a list of items instead of a simple message. In this case you’ll notice that the color of the text was not changed. You need to override the theme attribute textColorAlertDialogListItem for this text instead of textColorPrimary.

Part 3

Part 3: style the buttons

I want my button text blue and not italic, on a purple background.

Okay, first, sorry about my highly doubtful design tastes (this is just for the example’s purpose)… Anyway, the buttons at the bottom of the dialog use the theme attribute buttonBarButtonStyle. In Holo, this is redirected to another theme attribute, borderlessButtonStyle that references the style Widget.Holo.Button.Borderless. This style inherits from Widget.Holo.Button, where the color is defined (hardcoded), and the text appearance too (references to textAppearanceMedium). We need to define out own style for borderless buttons and a new text appearance.
For the background, the attribute used is buttonBarStyle. It references by default the style Holo.ButtonBar.AlertDialog.

To customise our button as needed, we need to add:

In sphinx_themes.xml,

In sphinx_styles.xml,

By defining a new text appearance based on the default Holo medium, we’re “forcing” our buttons back to normal, no italic.

And ta-dah!

Part 4

Part 4: style the divider

I want my divider purple.

The divider is that thin line between the title and the message. It is still showing the characteristic Holo light blue, and this can become an issue if you’re designing a nice completely custom UI based on other colors than Holo blue. I said nice UI, which is not our case in this example.
Bad news: there’s no easy way to change this color. Indeed, a look at the layout in the source code reveals that it is hardcoded, and therefore we cannot change it by a style attribute.
The only way to do it is to change it programmatically after our dialog has been built and shown. To do so:

 

The trick relies on the fact that we know the divider’s id is titleDivider. But even though this this view is present in an Holo layout, it may not be present in future releases of Android. For example, it has disappeared in Android L’s Material design. That’s why we check that the ID is non-null, and that’s why this trick can be considered as unstable.

But yay!

Part 5

Part 5: style the background

I want a red background behind my title.

We’ve been able to modify the colors and text appearances of everything in the dialog, but our background is still based on Holo! You may want to use a red background behind that green title (ouch), for instance. It is possible, but first let me warn you: this method is not straightforward, and it deals with the depths of Android, which can be hard to understand. By overriding Holo, you’ll have more freedom , but you’ll also lose a couple of nice features.

You remember that our custom theme Theme.Sphinx.Dialog.Alert is based on the (private) theme Theme.Holo.Dialog.Alert. This is convenient: it uses directly Holo background and layout for the dialog. Now if we want to define our custom background, we need to stop inheriting from Holo, like this:

 

But you also need to give your main theme an alertDialogStyle so that it can draw the background correctly:

Now it gets interesting. This style has to be something like:

There you have to define references to either colors or drawables. The way it works is quite complex: the actual layout of the AlertDialog is built by an internal component called AlertController that will assign the right background to each section (title, body, button bar…) by reading those style attributes. You can take a look at how it constructs the background here, but it’s hardly readable. Here are the attributes that you may want to change:

  • topDark for the title background
  • centerDark for the message background
  • centerBright for the background if your dialog displays a list
  • bottomMedium for the button bar background. Note that if you set this background, it looks better to remove the background in the style Sphinx.ButtonBar.AlertDialog.

Play around a little bit with those attribute to understand how they work. For a better visual result, you may also want to use your own drawables (with shadows) instead of plain colors.

Now, the big drawback of this method is that we lose cool features from Holo: the nice background with shadows, but also the style for the title. You’ll notice that our title is no longer green as defined in our windowTitleStyle style. This is because a basic layout for the dialog is inflated instead of Holo’s and in this layout, the TextView for the title doesn’t use the windowTitleStyle attribute. Instead, it uses the textAppearanceLarge. A fix for this is to define our title style TextAppearance.Sphinx.DialogWindowTitle as the textAppearanceLarge.

But this fix also has a bad consequence. In the AlertDialogs that display items instead of a message, those items actually use the textAppearanceLarge. Therefore they will look just like the title (minus the custom color textColorAlertDialogListItem)…

And that’s all we can do! You may tempted to change the layout of the dialog. Indeed there’s a layout attribute along with topDark, centerBottom and so on. But the best you can get by overriding this attribute is a crash of your application. I cannot explain it completely, but it seems that a whole bunch of internal components, private styles and hidden attributes prevent you to play with the layout of an AlertDialog. Too bad.

Complete source code

Let me share with you the complete source code for this tutorial.
The private Holo styles pumped from the source:

sphinx_themes.xml:

(Remember to modify the highlighted lines to choose between basic layout or Holo layout)

sphinx_styles.xml:

 

Conclusion

Now it’s over, you’re ready to style your dialogs like a pro! Please design something nicer than this ugly rainbow-like rectangle we came up with. I’d like to point out that the purpose of the method(s) presented is to be as lightweight, generic and reusable as possible. We take full advantage of the native Builder object, we don’t write a custom layout, and we only touch to XML styles.

It’s true that 3rd-party libs exist for this purpose, for example StyledDialogs. But because they are 3rd-party libs, they don’t work the exact same way. Plus they don’t support the full functionalities of AlertDialogs (item list or date picker, for example). You’re invited to take a look anyway! As we are talking about 3rd-party tools, I have to introduce you to the heavenly AndroidAssetStudio design suite. It has plenty of cool tools to help you design your 9-patch and icons for ActionBar, launcher, notification, etc. and to generate styles for your whole app! A true Android designer cannot work without these tools.

Dialogs are useful and if you’re reading this you probably need dialogs in your UI. But bear in mind that the concept of dialog itself is quite intrusive and disruptive. Modern UIs tend to use other components to fulfill the part of the dialogs, in a more smoothly way. You could imagine Toasts (with undo function), Notifications, or in-activity contextual appearing-disappearing messages. Always put your end-user at the center of your design!

When you design your AlertDialog theme, you have to test it in every condition. One important point is that if you use a Preference screen in your app, the preference dialogs will also use this theme. But you have no control on these: for example you won’t be able to change the color of the divider programmatically!

As a final word, did I use custom AlertDialogs in my app? No. I’m very perfectionist and I couldn’t get to the perfect result in my message-dialogs, my list-dialogs and my preference-dialogs at the same time. After a lot of tests, I finally decided that Holo dialogs were not so bad and that, after all, the user won’t be shocked as she/he sees Holo dialogs everywhere in the system.
Food for thought…

David,

facebooktwittergoogle_plusredditpinterestlinkedinmail

Have something to add?

Loading Facebook Comments ...

3 Comments

  1. David Ferrand
    Sep 22, 2014 @ 11:48:36

    @Eran,

    In your style TextAppearance.Sphinx.DialogWindowTitle, you can also define the size with the textSize attribute. For your second question, yes the display looks bad if you only specify colors. To have a proper dialog, you will need to create your own drawables (not just colors), with rounded corners, shadows, etc.

  2. Eran
    Sep 19, 2014 @ 15:31:29

    Great post, I tried following it but encountered some issues right at the part of customising the title background & font size.
    Seems like once I apply the style for the title, the font comes very small.
    Also, If I try to apply the background by adding the “AlertDialog_Sphinx”, with TopDark=”@color/somecolor”, The dialog will get the color but will display with very weird behavior (probably because lack of “parent”),
    Is there a way to overcome it?

  3. Anders
    Sep 04, 2014 @ 07:45:53

    Great blog post. I like how you decided to go for Holo after all in the end :)

Leave a Reply

*