web-dev-qa-db-fra.com

Problème de dialogue: requestFeature () doit être appelé avant d'ajouter du contenu

Je crée une boîte de dialogue personnalisée contenant un EditText afin que je puisse obtenir des données de texte de l'utilisateur:

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

Cependant, j'ai toujours cette 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)

...

à la ligne de dialog.show(). Que devrais-je faire pour m'en débarrasser?

16
fredley

Vous devez définir la vue personnalisée avant de créer la boîte de dialogue. De plus, vous devez utiliser setView(View) au lieu de setContentView() si vous utilisez les boutons positif et négatif par défaut fournis par la 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();
37
Cristian

Assurez-vous également que vous ne retournez pas une boîte de dialogue déjà affichée. Par exemple, ProgressDialog a une méthode statique pratique show() qui prend des paramètres et renvoie une ProgressDialog. Il s'avère que vous ne pouvez pas utiliser cette méthode et renvoyer la ProgressDialog résultante, car lorsque le système d'exploitation tente de l'afficher (et c'est déjà affiché), il lève cette même exception.

Attention aussi: le comportement ci-dessus est connu sur l'émulateur Android, mais il n'a pas généré d'exception et a très bien fonctionné sur mon Droid Incredible fonctionnant sous 2.2.

4
Ricket

Je l'ai rencontré il y a environ un an et je l'ai corrigé d'une manière qui utilise un code étrange. Encore une fois, une application sur laquelle je travaille a un fragment qui devrait s'afficher normalement sur le téléphone, mais dans un dialogue sur une tablette. Je l'ai résolu comme ça:

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

Cela me permet d’ajouter mon fragment comme n’importe quel fragment normal (dans une mise en page), mais aussi de l’afficher comme un dialogue où il s’exécute de manière autonome.

4
ar34z

Pour ceux qui ont ce problème en particulier avec DialogFragment.

Dans mon cas, cela s'est produit parce que j'étendais la classe DialogFragment de manière incorrecte. Je retournais une vue sur onCreateView() ET ÉGALEMENT en renvoyant une boîte de dialogue personnalisée sur onCreateDialog(). La documentation indique:

Vous pouvez avoir une conception d'interface utilisateur dans laquelle vous souhaitez qu'une partie de l'interface utilisateur apparaisse sous forme de dialogue dans certaines situations, mais sous forme de fragment plein écran ou incorporé dans d'autres (peut-être selon que le périphérique est un grand ou un petit écran). La classe DialogFragment vous offre cette flexibilité car elle peut toujours se comporter comme un fragment incorporable.

Cependant, vous ne pouvez pas utiliser AlertDialog.Builder ou d'autres objets Dialog pour construire la boîte de dialogue dans ce cas. Si vous souhaitez que DialogFragment puisse être intégré, vous devez définir l'interface utilisateur de la boîte de dialogue dans une présentation, puis chargez celle-ci dans le rappel onCreateView ().

Résolu le problème en ne créant rien sur onCreateDialog() (ne renvoyant que l'implémentation de la superclasse).

3
Gabriel Huff

J'avais un problème similaire. Mais mon dialogue devait être affiché pour IME. Lorsque je suis passé à Dialog au lieu de AlertDialog et que j'ai omis de créer, le programme a fonctionné pour moi.

2
Usha Hegde

Cela se produit également si vous essayez d'accéder à un élément de vue avec findViewById() avant onCreate(). Dans mon cas, c'est ce que j'ai fait:

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

la manière correcte d’éviter cette erreur est donc:

 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
Reejesh PK