对话问题:在添加内容之前必须调用requestFeature()

问题描述 投票:16回答:7

我正在创建一个包含EditText的自定义对话框,以便我可以从用户那里获取文本数据:

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

但是我总是得到这个例外:

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)

...

dialog.show()线。我应该怎么做才能摆脱这个?

android dialog
7个回答
37
投票

您需要在创建对话框之前设置自定义视图。如果你使用setView(View)为你提供的默认正负按钮,你还需要使用setContentView()而不是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();

4
投票

还要确保您没有返回已经显示的对话框。例如,ProgressDialog有一个方便的静态方法show(),它接受一些参数并返回ProgressDialog。事实证明你不能使用那个方法并返回生成的ProgressDialog,因为当OS试图显示它(并且它已经显示)时,它将抛出同样的异常。

请注意:上述行为是在Android模拟器上体验的,但它实际上没有抛出异常并且在我的Droid Incredible运行2.2上运行得很好。


4
投票

大约一年前我遇到过这种情况并使用奇怪的代码修复它。同样,我正在处理的应用程序有一个片段,应该在手机上正常显示,但在平板电脑上的对话框中。我这样解决了:

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

这允许我将我的片段添加为任何正常片段(在布局中),但也将其显示为自动运行的对话框。


3
投票

对于那些在使用DialogFragment时特别遇到此问题的人。

在我的情况下,发生这种情况是因为我错误地扩展了DialogFragment类。我在onCreateView()上返回了一个视图,并且还在onCreateDialog()上返回了一个自定义对话框。文件说明:

您可能有一个UI设计,在这种UI设计中,您希望UI的一部分在某些情况下显示为对话框,但在其他情况下则显示为全屏或嵌入式片段(可能取决于设备是大屏幕还是小屏幕)。 DialogFragment类为您提供了这种灵活性,因为它仍然可以表现为可嵌入的片段。

但是,在这种情况下,您无法使用AlertDialog.Builder或其他Dialog对象来构建对话框。如果希望DialogFragment可嵌入,则必须在布局中定义对话框的UI,然后在onCreateView()回调中加载布局。

通过不在onCreateDialog()上创建任何东西来解决问题(仅返回超类实现)。


2
投票

我遇到了类似的问题。但我的对话框将显示给IME。当我切换到Dialog而不是AlertDialog,并省略了创建时,该程序为我工作。


1
投票

如果你试图在findViewById()之前使用onCreate()访问任何视图项,也会发生这种情况。在我的情况下,我做了:

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

所以避免这个错误的正确方法是:

 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
    }}

1
投票

我的应用程序中有一个Alert对话框,它曾经在android API 23上给我这个android运行时异常。

原来这个问题与导入有关。我在进口中将android.app.AlertDialog改为androidx.appcompat.app.AlertDialog,问题解决了。

这适用于使用AndroidX工件的项目。如果您不使用AndroidX,请考虑使用支持版android.support.v7.app.AlertDialog


-3
投票

解决此问题的确切方法:

requestFeature(int)Window的一种方法。你必须导入这个类(android.view.Window)。

而且你必须得到AlertDialog.Builder对象的Window。然后打电话给requestFeature(int)。输入参数是Window的常量。

keyBuilder.getWindow().requestFeature(Window.FEATURE_ACTION_BAR);

© www.soinside.com 2019 - 2024. All rights reserved.