Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android - AlertDialog styling

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();

    }
like image 986
suresh cheemalamudi Avatar asked Feb 08 '13 10:02

suresh cheemalamudi


3 Answers

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

like image 99
David Wasser Avatar answered Nov 05 '22 00:11

David Wasser


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();   
            }
        });
like image 35
Kirk Avatar answered Nov 05 '22 02:11

Kirk


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.

like image 25
Chintan Rathod Avatar answered Nov 05 '22 01:11

Chintan Rathod