2011-01-11 9 views
13

Sto creando una finestra personalizzata contenente un EditText modo che io possa ottenere i dati di testo da parte dell'utente:problema Dialog: requestFeature() deve essere chiamato prima di aggiungere contenuti

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

Tuttavia ho sempre questa eccezione:

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) 

... 

alla riga dialog.show(). Cosa dovrei fare per sbarazzarmi di questo?

risposta

34

È necessario impostare la visualizzazione personalizzata prima di creare la finestra di dialogo. Inoltre, è necessario utilizzare setView(View) anziché setContentView() se si utilizzano i pulsanti positivi e negativi predefiniti forniti dallo 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(); 
+2

Sarebbe bello aggiungere un commento in modo che qualcun altro possa facilmente capire cosa è stato fatto diversamente senza dover confrontare il codice. – codinguser

+0

Hai ragione, amico ... non ho tempo adesso. Ti dispiacerebbe modificare la risposta per renderla più precisa? – Cristian

+3

Grazie! Mi hai salvato la giornata con "... è necessario utilizzare setview (View), invece di setContentView() ..." :) –

4

Assicurarsi inoltre di non restituire una finestra di dialogo già visualizzata. Ad esempio, ProgressDialog ha un pratico metodo statico show() che accetta alcuni parametri e restituisce un ProgressDialog. Si scopre che non è possibile utilizzare questo metodo e restituire il risultato ProgressDialog, perché quando il sistema operativo tenta di mostrarlo (ed è già mostrato), genererà la stessa eccezione.

Attenzione anche: il comportamento di cui sopra si verifica sull'emulatore Android, ma in realtà non ha generato un'eccezione e ha funzionato bene sul mio Droid Incredible in esecuzione 2.2.

2

Ho avuto un problema simile. Ma la mia finestra di dialogo doveva essere visualizzata per IME. Quando sono passato a Dialog invece di AlertDialog e omesso di creare, il programma ha funzionato per me.

-3

Il modo esatto per risolvere questo problema:

requestFeature(int) è un metodo di Window. Devi importare questa classe (android.view.Window).

E devi ottenere la finestra dell'oggetto AlertDialog.Builder. Quindi chiamare lo requestFeature(int). Il parametro di input è una costante di Window.

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

4

Ho incontrato questo circa un anno fa e riparato in modo utilizzando il codice strano. Ancora una volta, un'app a cui sto lavorando ha un frammento che dovrebbe essere visualizzato normalmente sul telefono, ma in un dialogo sul tablet. Ho risolto in questo modo:

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

Questo mi permette di aggiungere il mio frammento come qualsiasi frammento normale (in un layout), ma anche visualizzare come una finestra di dialogo in cui viene eseguito in modo autonomo.

3

Per coloro che hanno questo problema in particolare quando si utilizza DialogFragment.

Nel mio caso, questo è accaduto perché stavo estendendo la classe DialogFragment in modo errato. Stavo restituendo una vista su onCreateView() E ANCHE restituendo una finestra di dialogo personalizzata su onCreateDialog().La documentazione afferma:

si potrebbe avere una progettazione dell'interfaccia utente in cui si desidera un pezzo di interfaccia utente per apparire come una finestra di dialogo in alcune situazioni, ma come uno schermo pieno o frammento incorporato in altri (forse a seconda se il dispositivo è un grande schermo o uno schermo piccolo). La classe DialogFragment offre questa flessibilità perché può ancora comportarsi come un frammento incastrato .

Tuttavia, non è possibile utilizzare AlertDialog.Builder o altri oggetti di dialogo su creare la finestra di dialogo in questo caso. Se si desidera che DialogFragment sia incorporabile, è necessario definire l'interfaccia utente della finestra di dialogo in un layout, quindi caricare il layout nel callback onCreateView().

Risolto il problema non creando nulla su onCreateDialog() (solo restituendo l'implementazione della superclasse).

Problemi correlati