Проблема диалога: requestFeature () должен быть вызван перед добавлением контента - PullRequest
16 голосов
/ 11 января 2011

Я создаю пользовательский диалог, содержащий 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().Что мне делать, чтобы избавиться от этого?

Ответы [ 8 ]

37 голосов
/ 11 января 2011

Вам необходимо установить пользовательский вид перед созданием диалога. Также вам нужно использовать 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 голосов
/ 17 сентября 2015

Я столкнулся с этим около года назад и исправил это с помощью странного кода.Опять же, приложение, над которым я работаю, имеет фрагмент, который должен нормально отображаться на телефоне, но в диалоге на планшете.Я решил это так:

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

Это позволяет мне добавить свой фрагмент в качестве любого обычного фрагмента (в макете), но также отображать его в виде диалога, в котором он работает автономно.

4 голосов
/ 14 июня 2011

Также убедитесь, что вы не возвращаете уже показанный диалог. Например, ProgressDialog имеет удобный статический метод show(), который принимает некоторые параметры и возвращает ProgressDialog. Оказывается, вы не можете использовать этот метод и вернуть полученный ProgressDialog, потому что тогда, когда ОС попытается показать его (и он уже показан), она выдаст это же исключение.

Также будьте осторожны: вышеописанное поведение наблюдается на эмуляторе Android, но на самом деле оно не выдает исключение и отлично работает на моем Droid Incredible с 2.2.

3 голосов
/ 21 апреля 2016

Для тех, у кого возникла эта проблема именно при использовании DialogFragment.

В моем случае это произошло из-за того, что я неправильно расширял класс DialogFragment.Я возвращал представление о onCreateView() И ТАКЖЕ возвращал пользовательский диалог на onCreateDialog().Документация гласит:

У вас может быть дизайн пользовательского интерфейса, в котором вы хотите, чтобы часть пользовательского интерфейса отображалась как диалог в некоторых ситуациях, но как полноэкранный или встроенный фрагмент в других (возможно, в зависимости ото том, является ли устройство большим экраном или маленьким экраном).Класс DialogFragment предлагает вам эту гибкость, поскольку он все еще может вести себя как встраиваемый фрагмент.

Однако вы не можете использовать AlertDialog.Builder или другие объекты Dialog для построения диалога в этом случае.Если вы хотите, чтобы DialogFragment был встраиваемым, необходимо определить пользовательский интерфейс диалога в макете, а затем загрузить макет в обратном вызове onCreateView ().

Решил проблему, не создавая ничего на onCreateDialog()(возвращает только реализацию суперкласса).

2 голосов
/ 25 ноября 2011

У меня была похожая проблема.Но мой диалог должен был отображаться для IME.Когда я переключился на Dialog вместо AlertDialog и пропустил create, программа работала для меня.

1 голос
/ 17 февраля 2019

Это также происходит, если вы пытаетесь получить доступ к любому элементу просмотра с 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
    }}
0 голосов
/ 09 июля 2019

У меня в приложении был диалог Alert, и он давал мне это исключение времени выполнения Android на Android API 23.

Оказалось, что эта проблема была с импортом.Я изменил android.app.AlertDialog на androidx.appcompat.app.AlertDialog в импорте, и проблема была решена.

Это для проектов, в которых используются артефакты AndroidX.Если вы не используете AndroidX, рассмотрите вариант использования версии поддержки android.support.v7.app.AlertDialog.

0 голосов
/ 30 декабря 2012

Точный способ решения этой проблемы:

requestFeature(int) - это метод Window. Вы должны импортировать этот класс (android.view.Window).

И вам нужно получить окно объекта AlertDialog.Builder. Затем позвоните requestFeature(int). Входной параметр является константой Window.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...