Dialog problem: requestFeature() must be called before adding content
I'm creating a custom dialog containing an EditText so that I can get text data from the user:
final EditText newKey = (EditText) findViewById(R.id.dialog_result);
AlertDialog.Builder keyBuilder = new AlertDialog.Builder(StegDroid.this);
keyBuilder
.setCancelable(false)
.setPositiveButton("Try Again", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Log.v("Dialog","New Key: "+newKey.getText().toString());
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,开发者_开发技巧 int id) {
dialog.cancel();
}
});
AlertDialog dialog = keyBuilder.create();
dialog.setTitle("Decryption Failed");
dialog.setContentView(R.layout.decrypt_failed_dialog);
dialog.show();
However I always get this exception:
01-11 18:49:00.507: ERROR/AndroidRuntime(3461): android.util.AndroidRuntimeException: requestFeature() must be called before adding content
01-11 18:49:00.507: ERROR/AndroidRuntime(3461): at com.android.internal.policy.impl.PhoneWindow.requestFeature(PhoneWindow.java:181)
01-11 18:49:00.507: ERROR/AndroidRuntime(3461): at com.android.internal.app.AlertController.installContent(AlertController.java:199)
01-11 18:49:00.507: ERROR/AndroidRuntime(3461): at android.app.AlertDialog.onCreate(AlertDialog.java:251)
...
at the line of dialog.show()
. What should I be doing to get rid of this?
You need to set the custom view before creating the dialog. Also you need to use setView(View)
instead of setContentView()
if you are using the default positive and negative buttons provided for you by the AlertDialog
.
final EditText newKey = (EditText) findViewById(R.id.dialog_result);
AlertDialog.Builder keyBuilder = new AlertDialog.Builder(StegDroid.this);
keyBuilder
.setCancelable(false)
.setPositiveButton("Try Again", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Log.v("Dialog","New Key: "+newKey.getText().toString());
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
keyBuilder.setTitle("Decryption Failed");
keyBuilder.setView(getLayoutInflater().inflate(R.layout.decrypt_failed_dialog, null));
AlertDialog dialog = keyBuilder.create();
dialog.show();
Also make sure you are not returning an already-shown dialog. For example, ProgressDialog
has a handy static method show()
which takes some parameters and returns a ProgressDialog
. Turns out you can't use that method and return the resulting ProgressDialog
, because then when the OS tries to show it (and it's already shown), it will throw this same exception.
Beware, too: the above behavior is experienced on the Android emulator, but it actually did not throw an exception and worked just fine on my Droid Incredible running 2.2.
I had an Alert dialog in my app and it used to give me this android runtime exception on android API 23.
Turned out this problem was with the import. I changed android.app.AlertDialog
to androidx.appcompat.app.AlertDialog
in the imports and the problem was solved.
This is for projects that use AndroidX Artifacts. Consider using the Support version android.support.v7.app.AlertDialog
if you are not using AndroidX.
I've ran into this about a year ago and fixed it in a way using weird code. Again, an app I'm working on has a fragment that should display normally on phone, but in a dialogue on tablet. I solved it like this:
public class MyDialogFragment extends DialogFragment {
private View mLayout;
private ViewGroup mContainer;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mContainer = container;
if (getShowsDialog()) {
// one could return null here, or be nice and call super()
return super.onCreateView(inflater, container, savedInstanceState);
}
return getLayout(inflater, container);
}
private View getLayout(LayoutInflater inflater, ViewGroup container) {
mLayout = inflater.inflate(R.layout.my_layout, container, false);
return mLayout;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
return new AlertDialog.Builder(getContext())
.setPositiveButton(R.string.ok, null)
.setNegativeButton(R.string.cancel, null)
.setNeutralButton(R.string.filter_clear_selection, null)
.setView(getLayout(LayoutInflater.from(getContext()), mContainer))
.create()
;
}
}
This allows me to add my fragment as any normal fragment (in a layout), but also display it as a dialog where it runs autonomously.
For those who are having this problem specifically when using DialogFragment
.
In my case, this was happened because I was extending the DialogFragment
class incorrectly. I was returning a view on onCreateView()
AND ALSO returning a custom dialog on onCreateDialog()
. The documentation states:
You might have a UI design in which you want a piece of the UI to appear as a dialog in some situations, but as a full screen or embedded fragment in others (perhaps depending on whether the device is a large screen or small screen). The DialogFragment class offers you this flexibility because it can still behave as an embeddable Fragment.
However, you cannot use AlertDialog.Builder or other Dialog objects to build the dialog in this case. If you want the DialogFragment to be embeddable, you must define the dialog's UI in a layout, then load the layout in the onCreateView() callback.
Solved the problem by not creating anything on onCreateDialog()
(only returning the superclass implementation).
I had a similar problem. But my dialog was to be displayed for IME. When I switched to Dialog instead of AlertDialog, and omitted create, the program worked for me.
I also had this error message when using a DialogFragment.
My problem was solved when in the onCreateDialog(Bundle savedInstanceState)
I changed the dialog that I returned
from
android.appAlertDialog
to
androidx.appcompat.app.AlertDialog
(or if you haven't migrate to AndroidX, then android.support.v7.app.AlertDialog
)
This also happens if you try to access any view item with findViewById()
before the onCreate()
That is in my case i did:
private class ShareViaDialog extends Dialog {
private ImageView mainSmallIcon = findViewById(R.id.mainSmallIcon); //this is wrong
@Override
protected void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
}}
so the correct way to avoid this error is:
private class ShareViaDialog extends Dialog {
private ImageView mainSmallIcon;
@Override
protected void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
mainSmallIcon = findViewById(R.id.mainSmallIcon); //should be here
}}
The exact way to solve this problem:
requestFeature(int)
is a method of Window
. You have to import this class (android.view.Window
).
And you have to get the Window of the AlertDialog.Builder object. Then call requestFeature(int)
. The input parameter is a constant of Window.
keyBuilder.getWindow().requestFeature(Window.FEATURE_ACTION_BAR);
精彩评论