Button style in AlertDialogs
Asked Answered
N

8

30

Does anyone know how to override the default style for AlertDialog buttons? I've looked through the Android source for themes and styles and experimented with different things but I haven't been able to find a way that works.

What I've got below works for changing the backgrounds, but doesn't do anything with the buttons. myTheme is applied to the whole <application> via the manifest. (Some other items were deleted for clarity, but they only relate to the title bar.)

<style name="myTheme" parent="android:Theme">
    <item name="android:buttonStyle">@style/customButtonStyle</item>
    <item name="android:alertDialogStyle">@style/dialogAlertTheme</item>
</style>

<style name="dialogAlertTheme" parent="@android:style/Theme.Dialog.Alert">
    <item name="android:fullDark">@drawable/dialog_loading_background</item>
    <item name="android:topDark">@drawable/dialog_alert_top</item>
    <item name="android:centerDark">@drawable/dialog_alert_center</item>
    <item name="android:bottomDark">@drawable/dialog_alert_bottom</item>
    <!-- this last line makes no difference to the buttons -->
    <item name="android:buttonStyle">@style/customButtonStyle</item> 
</style>

Any ideas?

Nikko answered 26/3, 2010 at 14:41 Comment(1)
Z
1

See all other anwsers below.

Incorrect:

I guess you have to implement your own Dialog class.

Zadoc answered 26/3, 2010 at 14:56 Comment(3)
Hmm. That'd be annoying; changing Dialog buttons shouldn't be that an unusual of a thing to do, considering that it's easy to apply a button style to the 'normal' Activity buttons.Nikko
In normal activities you define the layout of the content view with an xml. Dialog does this for you, so you don't have access to the layout xml. Implementing your own dialog (possibly with only a setContentView() call) allows you to use a different xml and thus different styles for buttons.Zadoc
How would you subclass AlertDialog so that you could use AlertDialog.Builder with your subclass?Chainplate
B
29

Given that MrSnowflake's reasoning is inaccurate, I'm taking the freedom to provide another answer.

There is something wrong with the markup in Steve Haley's question, and it is mixing up alertDialogStyle and alertDialogTheme, most likely because of the fact that alertDialogTheme was introduced long after alertDialogStyle was around.

So even if @android:style/Theme.Dialog.Alert is available on your Andoid platform, you still can't utilize its expressional power by hooking a cusomized version back into your own theme unless your Android platform supports an android:alertDialogTheme attribute/item for themes. (It may or may not be the case that such inconsistent Android versions exist, I don't know for sure. But the markup used in the question suggests that it does.)

In the question's markup, the parent="@android:style/Theme.Dialog.Alert" will do nothing except creating the illusion that you're customizing the alert dialog theme when you're really only customizing the alert dialog style.

This is how the markup should look like; not all Android versions support all features.

<style name="myTheme" parent="android:Theme">
    <item name="android:buttonStyle">@style/customButtonStyle</item>
    <item name="android:alertDialogStyle">@style/dialogAlertStyle</item>
    <item name="android:alertDialogTheme">@style/dialogAlertTheme</item>
</style>

<style name="dialogAlertStyle" parent="@android:style/AlertDialog">
    <item name="android:fullDark">[...]</item>
    [...]
</style>

<style name="dialogAlertTheme" parent="@android:style/Theme.Dialog.Alert">
    <item name="android:windowBackground">[...]</item>
    [...]
</style>

Customizing the alert dialog style has been around for quite some time but is limited to providing (background) drawables for "fullDark", "topDark" etc.

Customizing the alert dialog theme opens a method to provide attributes such as windowBackground, windowTitleStyle and such, but as stated before, you need an Android version which supports the alertDialogThem attribute/item for themes. I can't figure out exactly when this was introduced but it hasn't been Android 2.2 and Eclipse will tell you anyway...

I don't have the resources to validate MrSnowflake's conclusion that it's impossible to style alert dialog buttons in XML, but unless we're facing one of those somewhat nasty aspects of Android where a feature is really missing, I find it unlikely.

As a matter of fact, what's missing in the question is the most relevant part in this respect, namely

<style name="customButtonStyle" />

so the conclusion that alert dialog buttons do not obey the Widget.Button is not yet proven from my point of view.

Consolidated conclusion: The abilities to style alert dialogs independently of other widgets is limited in Android but getting more powerful as new versions improve in this respect.

Brandy answered 7/12, 2012 at 11:39 Comment(5)
Here worked only after I removed the 'android:' part from 'android:alertDialogTheme'. Thanks.Satterlee
@Satterlee Interesting, that could break compatibility with older Android versions, unless it was optional in the past and is no longer accepted now. Have you made compatibility tests? Even if not: For which Android version does it work like you describe?Brandy
I get a build error when I add parent="@android:style/AlertDialog" to dialogAlertStyle: resource android:style/AlertDialog is private. Same with the theme.Gait
@DavidKennedy Thank you for letting me know. And that is for which Android version?Brandy
My compile SDK version is 28. Is that what you need to know?Gait
H
11

Try this:

 <item name="buttonBarStyle">@style/Widget.AppCompat.ButtonBar</item>
    <item name="buttonBarButtonStyle">@style/AppTheme.Button</item>
    <item name="buttonBarPositiveButtonStyle">@style/YoursTheme</item>
    <item name="buttonBarNegativeButtonStyle">@style/YoursTheme</item>
    <item name="buttonBarNeutralButtonStyle">@style/YoursTheme</item>
Hagans answered 26/7, 2016 at 14:4 Comment(2)
This would be more useful if you'd explain where these lines should be placed. I sure can't figure it out ...Continuation
Thank you for that, was looking for it for hours! @Continuation you should place it into your Dialog theme, a theme that should probably extend ThemeOverlay.AppCompat.Dialog.Alert and that you declare in your theme using <item name="alertDialogTheme">@style/YourDialogTheme</item>Dincolo
M
7

You can override "buttonBarButtonStyle" instead of "buttonStyle" like this:

<style name="dialogAlertTheme" parent="@android:style/Theme.Dialog.Alert">
  <item name="android:buttonBarButtonStyle">@style/customButtonStyle</item>
</style>
Mochun answered 24/7, 2014 at 10:9 Comment(3)
requires API 11 or higherOndrej
@TimCastelijns I feel that's beside the point. A quality answer should provide that piece of information. And there are in fact cases where people have to maintain backwards compatible apps.Brandy
I get a build error when I add parent="@android:style/AlertDialog" to dialogAlertTheme: resource android:style/Theme.Dialog.Alert is private. Changing the parent to ThemeOverlay.AppCompat.Dialog.Alert as suggested by @Dincolo seems to work.Gait
R
5

If you're using Material Components:

<style name="AppTheme" parent="Theme.MaterialComponents.Light.DarkActionBar">
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
    <item name="android:alertDialogTheme">@style/AlertDialogTheme.Light</item>
</style>

<style name="AlertDialogTheme.Light" parent="ThemeOverlay.MaterialComponents.Dialog.Alert" >
    <item name="android:buttonBarButtonStyle">@style/InsertCustomButtonStyleHere</item>
</style>

This will keep your theme's colors but replace the style of the buttons, for instance to match Widget.MaterialComponents.Button.TextButton.

Recept answered 11/12, 2018 at 20:32 Comment(1)
With this approach, I was able to change the text size but not colors. See https://mcmap.net/q/112884/-material-design-not-styling-alert-dialogs for a more comprehensive solution.Gait
T
3

I made a method like this that will change the default button colors and background

public static void setDefaultColorTextForDialogButton(AlertDialog alertDialog, Resources r) {
    Button b;

    b= alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE);
    if(b != null) {
        b.setTextColor(r.getColor(R.color.default_text));
        b.setBackgroundColor(Color.WHITE);
    }
    b = alertDialog.getButton(DialogInterface.BUTTON_POSITIVE);
    if(b != null) {
        b.setTextColor(r.getColor(R.color.default_text));
        b.setBackgroundColor(Color.WHITE);
    }
    b = alertDialog.getButton(DialogInterface.BUTTON_NEUTRAL);
    if(b != null) {
        b.setTextColor(r.getColor(R.color.default_text));
        b.setBackgroundColor(Color.WHITE);
    }
}

This could be useful for some people!!!

Topminnow answered 24/3, 2015 at 17:51 Comment(1)
In an OO language such as Java, this is really not the preferred way of doing things, especially considering maintainability.Brandy
Z
1

See all other anwsers below.

Incorrect:

I guess you have to implement your own Dialog class.

Zadoc answered 26/3, 2010 at 14:56 Comment(3)
Hmm. That'd be annoying; changing Dialog buttons shouldn't be that an unusual of a thing to do, considering that it's easy to apply a button style to the 'normal' Activity buttons.Nikko
In normal activities you define the layout of the content view with an xml. Dialog does this for you, so you don't have access to the layout xml. Implementing your own dialog (possibly with only a setContentView() call) allows you to use a different xml and thus different styles for buttons.Zadoc
How would you subclass AlertDialog so that you could use AlertDialog.Builder with your subclass?Chainplate
M
0

This allowed me to customize my AlertDialog buttons and layout.

private void openLookupTableEditDialog() {
    AlertDialog.Builder openLookupTableEditDialog = new AlertDialog.Builder(this);
    View v = this.getLayoutInflater().inflate(R.layout.lookup_table_edit_dialog, null);

    openLookupTableEditDialog.setView(v);
    final AlertDialog alert = openLookupTableEditDialog.create();
    openLookupTableEditDialog.setTitle("Lookup Table Edit");
    Button btnSpecies = v.findViewById(R.id.btnSpeciesLookupEdit);
    Button btnLocation = v.findViewById(R.id.btnLocationLookupEdit);
    Button btnSampler = v.findViewById(R.id.btnSamplerLookupEdit);
    Button btnExit = v.findViewById(R.id.btnCloseLookupTableEdit);
    alert.setView(v);
    alert.show();

    btnSpecies.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {
            editSpeciesTable();
            alert.dismiss();
        }
    });
    btnSampler.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {
            editSamplerTable();
            alert.dismiss();
        }
    });
    btnLocation.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {
            editLocationTable();
            alert.dismiss();
        }
    });
    btnExit.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {
           alert.dismiss();
        }
    });
    ...
}
Merta answered 7/5, 2021 at 15:43 Comment(0)
I
0

In kotlin it would be like this:

private fun showDialog() =
    AlertDialog.Builder(requireContext())
        .setTitle("Title")
        .setMessage("Message")
        .setPositiveButton("OK") { _, _ ->
            // Code
        }
        .setNegativeButton("Cancel") { _, _ -> 
            // Code
        }
        .show()
        .apply {
            getButton(DialogInterface.BUTTON_POSITIVE).apply{
                setTextColor(ContextCompat.getColor(requireContext(), R.color.colorPrimary));
            }
            getButton(DialogInterface.BUTTON_NEGATIVE).apply{
                setTextColor(ContextCompat.getColor(requireContext(), R.color.colorSecondary));
            }
        }
Immixture answered 17/3, 2023 at 23:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.