2011-01-11 14 views
13

Estoy creando un diálogo personalizado que contiene un EditarTexto para que pueda obtener los datos de texto del usuario:problema de diálogo: requestFeature() debe ser llamado antes de añadir contenido

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

Sin embargo siempre consigo esta excepción:

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) 

... 

en la línea de dialog.show(). ¿Qué debería hacer para deshacerme de esto?

Respuesta

34

Debe configurar la vista personalizada antes de crear el cuadro de diálogo. También necesita usar setView(View) en lugar de setContentView() si está utilizando los botones positivos y negativos predeterminados proporcionados por el 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

Sería bueno agregar un comentario para que otra persona pueda entender fácilmente lo que se hizo de manera diferente sin tener que comparar el código. – codinguser

+0

Tienes razón amigo ... No tengo tiempo ahora. ¿Te importaría editar la respuesta para que sea más precisa? – Cristian

+3

Gracias! Me salvaste el día con "... necesitas usar setView (Ver) en lugar de setContentView() ..." :) –

4

también asegurarse de que no devuelve un cuadro de diálogo mostrado ya. Por ejemplo, ProgressDialog tiene un práctico método estático show() que toma algunos parámetros y devuelve ProgressDialog. Resulta que no puede usar ese método y devolver el resultante ProgressDialog, porque luego, cuando el sistema operativo intente mostrarlo (y ya se muestra), generará la misma excepción.

Tenga cuidado, también: el comportamiento anterior se experimenta en el emulador de Android, pero en realidad no arrojó una excepción y funcionó bien en mi Droid Incredible corriendo 2.2.

2

Tuve un problema similar. Pero mi diálogo debía mostrarse para IME. Cuando cambié a Dialog en lugar de AlertDialog, y omití crear, el programa funcionó para mí.

-3

La forma exacta para resolver este problema:

requestFeature(int) es un método de Window. Tienes que importar esta clase (android.view.Window).

Y debe obtener la ventana del objeto AlertDialog.Builder. Luego llame al requestFeature(int). El parámetro de entrada es una constante de Ventana.

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

4

He encontré con esto hace un año y se fija de una manera usando el código extraño. De nuevo, una aplicación en la que estoy trabajando tiene un fragmento que debería mostrarse normalmente en el teléfono, pero en un diálogo en una tableta. Lo resuelto de esta manera:

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

Esto me permite añadir mi fragmento como cualquier fragmento de lo normal (en un diseño), sino también mostrarlo como un diálogo en el que se ejecuta de forma autónoma.

3

Para aquellos que tienen este problema específicamente cuando usan DialogFragment.

En mi caso, esto sucedió porque estaba ampliando la clase DialogFragment incorrectamente. Estaba devolviendo una vista en onCreateView() Y TAMBIÉN devolviendo un diálogo personalizado en onCreateDialog().La documentación indica:

Es posible que tenga un diseño de interfaz de usuario en la que desea un pedazo de la interfaz de usuario a aparecer como un cuadro de diálogo en algunas situaciones, sino como una pantalla completa o fragmento incrustado en otros (tal vez en función de si el dispositivo es una pantalla grande o una pantalla pequeña). La clase DialogFragment ofrece esta flexibilidad, ya que aún se puede comportar como un fragmento incrustado.

Sin embargo, no puede usar AlertDialog.Builder u otros objetos de diálogo a construir el cuadro de diálogo en este caso. Si desea que el DialogFragment sea incrustable, debe definir la interfaz de usuario del cuadro de diálogo en un diseño, luego cargar el diseño en la devolución de llamada onCreateView().

Resolvió el problema al no crear nada en onCreateDialog() (solo devolvía la implementación de la superclase).

Cuestiones relacionadas