Android - AlertDialog styling
Asked Answered
D

4

8

I have an alert dialog in the app as shown below.

enter image description here

I want the title and the line which separates the title - message body to be in orange colour. how can i do this? What i tried is using custom style as shown below. But this did not work.

<style name="AboutDialog" parent="@android:style/Theme.Dialog">
  <item name="android:textColor">#E5492A</item>
</style>

my alert dialog code:

AlertDialog.Builder alertDialog = new AlertDialog.Builder( new ContextThemeWrapper(MainActivity.context, R.style.AboutDialog));
alertDialog.setTitle("Sample");
        alertDialog.setMessage(R.string.rate_dialog_text);
        alertDialog.setPositiveButton(R.string.rate_now_text,
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        MainActivity.context.startActivity(new Intent(
                                Intent.ACTION_VIEW, Uri
                                        .parse("market://details?id="
                                                + MainActivity.APP_PNAME)));
                        if (editor != null) {
                            editor.putBoolean("dontshowagain", true);
                            editor.commit();
                        }
                        dialog.dismiss();

                    }
                });

        alertDialog.setNeutralButton(R.string.remind_later_text,
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();
                    }
                });

        alertDialog.setNegativeButton(R.string.no_thanks_text,
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        if (editor != null) {
                            editor.putBoolean("dontshowagain", true);
                            editor.commit();
                        }
                        dialog.dismiss();
                    }
                });

        return alertDialog.create();

    }
Dicho answered 8/2, 2013 at 10:23 Comment(0)
P
18

Instead of:

AlertDialog.Builder alertDialog = new AlertDialog.Builder(
    new ContextThemeWrapper(MainActivity.context, R.style.AboutDialog));

Try this:

AlertDialog.Builder alertDialog = new AlertDialog.Builder(this, R.style.AboutDialog);

NOTE: This is only available for API 11 (Android 3.0) and above.

If you need to to support Android < 3.0 you probably have to create a custom dialog (instead of using AlertDialog

EDIT Added really sleazy reflection-based hack

If you are really stuck and don't want to implement a custom dialog, then try the following.

After you've built the dialog and just before you want to return it, instead of this:

return alertDialog.create();

do this:

AlertDialog ad = alertDialog.create(); // Create the dialog
// Add listener so we can modify the dialog before it is shown
ad.setOnShowListener(new DialogInterface.OnShowListener() {
    @Override
    public void onShow(DialogInterface dialogInterface) {
        // Set the text color on the dialog title and separator
        setTextColor(dialogInterface, 0xFFE5492A);
    }
});
return ad;

Now add this very nasty reflection-based method:

public void setTextColor(DialogInterface alert, int color) {
    try {
        Class c = alert.getClass();
        Field mAlert = c.getDeclaredField("mAlert");
        mAlert.setAccessible(true);
        Object alertController = mAlert.get(alert);
        c = alertController.getClass();
        Field mTitleView = c.getDeclaredField("mTitleView");
        mTitleView.setAccessible(true);
        Object dialogTitle = mTitleView.get(alertController);
        TextView dialogTitleView = (TextView)dialogTitle;
        // Set text color on the title
        dialogTitleView.setTextColor(color);
        // To find the horizontal divider, first
        //  get container around the Title
        ViewGroup parent = (ViewGroup)dialogTitleView.getParent();
        // Then get the container around that container
        parent = (ViewGroup)parent.getParent();
        for (int i = 0; i < parent.getChildCount(); i++) {
            View v = parent.getChildAt(i);
            if (v instanceof ImageView) {
                // We got an ImageView, that should be the separator
                ImageView im = (ImageView)v;
                // Set a color filter on the image
                im.setColorFilter(color);
            }
        }
    } catch (Exception e) {
        // Ignore any exceptions, either it works or it doesn't
    }
}

I tested this on Android 2.2 and Android 4.0 and it works. It may not do exactly what you want, so you'll need to try it. I can't guarantee it will work on all devices or on future versions of Android, since it depends a lot on the way the AlertDialog class is implemented (if they change that in the future this probably won't work anymore).

Just a few notes for anyone who cares:

  1. The reason that I use setOnShowListener() is because you can't actually get to the internal View objects that AlertDialog uses until after they have been inflated. They don't get inflated immediately when you create an AlertDialog, it happens some time later. Using the listener we can get control after the layout is inflated but before the Dialog is shown.

  2. I'm using reflection to access in internal member variables in the AlertDialog implementation. Once I get access to the TextView that contains the title, I have to monkey around to find the horizontal line that is used to separate the title from the message. To do this I get the Layout that surrounds the title (this Layout contains the alert icon and title text). Then I get the Layout that surrounds that (this Layout wraps the icon, title text and the separator). Then I look at all children of the surrounding layout and set the color on all ImageView objects in there. The separator is implemented as an ImageView using a drawable, therefore it isn't possible to just change the color. Note: An alternative to using setColorFilter() would be to replace the drawable in the ImageView with a suitably colored drawable here.

Thanks for the challenge, it was kinda fun to figure this out :-D

Plascencia answered 8/2, 2013 at 10:41 Comment(7)
am still unable to make it work. this is what i get if done as u sugested. i.imgur.com/aEUuCbE.pngDicho
Added another solution based on reflection. Hope that helps.Plascencia
thanks for the brilliant hack. It should work. But after using this logic what i am getting is like shown here i.imgur.com/zCjvsrf.pngDicho
Have you set a theme on your application or your activity in the manifest? What version of Android OS are you using? Is this on an emulator or a device? If device, what device?Plascencia
Ya. I have set my custom theme in manifest to style action bar. I guess this is giving some problem. I am using JB. its on device. Nexus 7Dicho
You can try going back to AlertDialog.Builder alertDialog = new AlertDialog.Builder(new ContextThemeWrapper(MainActivity.context, R.style.AboutDialog)); and see if that changes anything. For some reason you are using another theme.Plascencia
OK. Please let me know the results.Plascencia
X
2

by the way its a late answer, maybe it will be useful for someone. to create Custom AlertDialog and have the same neat buttons like the Default AlertDialog. follow the simple method below

final AlertDialog.Builder demoDialog = new AlertDialog.Builder(this);
        final LayoutInflater inflator = this.getLayoutInflater();
        final View view = inflator.inflate(R.layout.passcode_req_dialog_template, null);

        demoDialog.setView(view)

            .setPositiveButton(R.string.ok_button_text, new DialogInterface.OnClickListener() {

                @Override
                public void onClick(DialogInterface dialog, int which) {

                }
            })

            .setNegativeButton(R.string.cancel_button_text, new DialogInterface.OnClickListener() {

                @Override
                public void onClick(DialogInterface dialog, int which) {

                }
            });

        final AlertDialog dialog = passwordDialog.create();
        dialog.show();
        dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {

                //Get the work done here when pressing positive button
                dialog.dismiss(); 
            }
        });

        dialog.getButton(AlertDialog.BUTTON_NEGATIVE).setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {

                //Get the work done here when pressing negative button
                dialog.dismiss();   
            }
        });
Xiomaraxiong answered 16/12, 2013 at 12:11 Comment(0)
P
1

Try to create a custom layout for dialog and provide that layout to your alert dialog by using

dialog.setContentView(R.layout.customDialogLayout);

You can see this example for custom dialog.

Pelvis answered 8/2, 2013 at 10:44 Comment(4)
I dont wanted to use custom dialog. because the buttons in custom dialog looks something like this i.imgur.com/aEUuCbE.png . but i want something like shown in the question which is smooth and neat. can i achieve this using custom dialog?Dicho
of course, you can. You can design your layout from any graphics developer, who tell you all necessary color code, text size, text color and borders etc.Pelvis
can u please show me some tutorial or sample code to get the buttons in custom layout as shown in the question?Dicho
You can create a TableLayout having 3 columns. Each have a TextView with gray background.Pelvis
M
0

Your can use this project AlertDialogPro. Include this project to yours and define your theme like below:

<style name="YourAppTheme.AlertDialogProTheme" parent="AlertDialogProTheme.Holo.Light">
    <!-- Custom the title -->
    <item name="android:windowTitleStyle">@style/YourDialogWindowTitle</item>
    <!-- Change the title line to orange -->
    <item name="adpTitleDividerBackground">#E5492A</item>
</style>

<style name="YourDialogWindowTitle" parent="DialogWindowTitle.Holo.Light">
    <item name="android:textColor">#E5492A</item>
</style>

And specify this theme to your app's theme with attribute "alertDialogProTheme":

<style name="AppTheme" parent="AppBaseTheme">
  ...
  <item name="alertDialogProTheme">@style/YourAppTheme.AlertDialogProTheme</item>
</style>

Use AlertDialogPro.Builder to build dialog:

AlertDialogPro.Builder builder = new AlertDialogPro.Builder(getContext());
builder.setTitle(R.string.app_name).
    setMessage("Message").
    setPositiveButton("Rate Now", null).
    setNeutralButton("Remind me later", null).
    setNegativeButton("No,thanks", null).
    show();

screenshot

Maisel answered 6/10, 2014 at 3:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.