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

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();
}
回答1:
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:
The reason that I use
setOnShowListener()
is because you can't actually get to the internalView
objects thatAlertDialog
uses until after they have been inflated. They don't get inflated immediately when you create anAlertDialog
, it happens some time later. Using the listener we can get control after the layout is inflated but before theDialog
is shown.I'm using reflection to access in internal member variables in the
AlertDialog
implementation. Once I get access to theTextView
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 theLayout
that surrounds the title (thisLayout
contains the alert icon and title text). Then I get theLayout
that surrounds that (thisLayout
wraps the icon, title text and the separator). Then I look at all children of the surrounding layout and set the color on allImageView
objects in there. The separator is implemented as anImageView
using a drawable, therefore it isn't possible to just change the color. Note: An alternative to usingsetColorFilter()
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
回答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();
}
});
回答3:
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.
回答4:
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();

来源:https://stackoverflow.com/questions/14770400/android-alertdialog-styling