Platform version independent custom dialog with standard icon, title and buttons
-
19-03-2021 - |
Question
What I'm trying to archive: I want a dialog with a custom view in it, but I want the standard icon, title, buttons from the AlertDialog
.
What I'm doing is this custom dialog class:
public class CustomDialog extends AlertDialog.Builder {
private Activity activity;
private View root;
public CustomDialog(Activity context) {
super(context);
this.activity = context;
}
public void setView(int layoutResID) {
LayoutInflater inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
root = inflater.inflate(layoutResID, (ViewGroup) activity.findViewById(R.id.dialog_root), false);
ScrollView scroller = new ScrollView(activity);
scroller.addView(root);
setView(scroller);
}
public void setCustomView(View v) {
ScrollView scroller = new ScrollView(activity);
scroller.addView(v);
setView(scroller);
}
public View getRoot() {
return root;
}
@Override
public AlertDialog create() {
AlertDialog dialog = super.create();
dialog.getWindow().getAttributes().width = LayoutParams.MATCH_PARENT;
return dialog;
}
}
This works pretty good, expect the TextView
colors aren't correct on pre-Honeycomb and Honeycomb devices. I'm using the Holo.Light
theme so the standard text color is black, but the background color of dialogs on pre-Honeycomb devices too. And on Honeycomb devices the dialog background is white. So what I did is, I added a dialogTextColor=white
in the styles.xml
in the values
folder and dialogTextColor=black
in the values-v11
folder. Then I had to add the style attribute to every TextView
that I'm using in a custom dialog. This worked out until ICS and it's clear why -> v11. I could change it, but I want to have a custom dialog which does everything correct: The text color on pre-Honeycomb, Honeycomb, ICS (and whatever will come in the future) based on the application theme, the width of the dialog, the standard buttons, title, icon from the AlertDialog
.
Solution
The trick here is that a Context is associated with a theme. That theme determines all sorts of things like default text colors, etc.
Before Honeycomb Dialogs always had the same theme whether they were generated from light or dark themed Activities, and with the exception of lists Dialogs were dark background, light foreground. In Honeycomb and forward, Dialogs have different themes determined by the Activity that spawns them.
When inflating content in a Dialog, always use the Context returned by the Dialog#getContext()
method instead of the Activity that spawned the Dialog. Instead of the line of code you use to get your LayoutInflater
above, try:
LayoutInflater inflater = LayoutInflater.from(getContext());
Edit: It looks like you're using an AlertDialog.Builder instead of a Dialog. AlertDialog.Builder added a getContext()
method for this purpose in API 11 (Android 3.0, a.k.a. Honeycomb) but it didn't exist before that. You can build your own themed context with a ContextThemeWrapper
for older devices. Just make sure you never try to call that method on an older version of the platform. You can guard it with a simple check:
Context themedContext;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
themedContext = getContext();
} else {
themedContext = new ContextThemeWrapper(activity, android.R.style.Theme_Dialog);
}
LayoutInflater inflater = LayoutInflater.from(themedContext);