Se debe llamar a requestFeature () antes de agregar contenido

135

Estoy tratando de implementar una barra de título personalizada:

Aquí está mi clase de ayudante:

import android.app.Activity;
import android.view.Window;

public class UIHelper {
    public static void setupTitleBar(Activity c) {
        final boolean customTitleSupported = c.requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);

        c.setContentView(R.layout.main);

        if (customTitleSupported) {
            c.getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.titlebar);
        }
    }
}

Aquí es donde lo llamo en onCreate ():

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setupUI();
}

private void setupUI(){
     setContentView(R.layout.main);
     UIHelper.setupTitleBar(this);
}

Pero me sale el error:

requestFeature() must be called before adding content
Sheehan Alam
fuente

Respuestas:

331

Bueno, solo haz lo que te dice el mensaje de error.

No llames setContentView()antes requestFeature().

Nota:

Como se dijo en los comentarios, para ambos ActionBarSherlocky la AppCompatbiblioteca, es necesario llamar requestFeature()antessuper.onCreate()

Octavian A. Damiean
fuente
6060
maldita sea, esta es una respuesta con clase.
Una persona
6060
Para ActionBarSherlock, también es necesario llamar requestFeature()antes super.onCreate(). Referencia: github.com/JakeWharton/ActionBarSherlock/issues/…
Saran
1
¿Qué sucede si necesita mostrar un diseño sin una barra de título y luego mostrar uno con una barra de título? Tendrá que usar requestWindowFeature(Window.FEATURE_NO_TITLE)para ocultarlo, luego setContentView()para su primer diseño, luego requestWindowFeature(Window.FEATURE_CUSTOM_TITLE)para mostrar la barra de título nuevamente. Eso sería después de setContentView()la segunda vez.
msbg
35
Es el mismo caso en AppCompat que @Saran dijo. Debe llamar a su requestFeatureantessuper.onCreate()
Jaison Brooks
77
Esta respuesta no ayuda mucho ... pero ¿qué sé?
Ojonugwa Jude Ochalifu
23

Sé que tiene más de un año, pero llamar requestFeature()nunca resolvió mi problema. De hecho, no lo llamo en absoluto.

Supongo que era un problema al inflar la vista. A pesar de todas mis búsquedas, nunca encontré una solución adecuada hasta que jugué con los diferentes métodos para inflar una vista.

AlertDialog.Builder es la solución fácil pero requiere mucho trabajo si usa el onPrepareDialog()para actualizar esa vista.

Otra alternativa es aprovechar AsyncTask para los diálogos.

Una solución final que utilicé es la siguiente:

public class CustomDialog extends AlertDialog {

   private View content;

   public CustomDialog(Context context) {
       super(context);

       LayoutInflater li = LayoutInflater.from(context);
       content = li.inflate(R.layout.custom_view, null);

       setUpAdditionalStuff(); // do more view cleanup
       setView(content);           
   }

   private void setUpAdditionalStuff() {
       // ...
   }

   // Call ((CustomDialog) dialog).prepare() in the onPrepareDialog() method  
   public void prepare() {
       setTitle(R.string.custom_title);
       setIcon( getIcon() );
       // ...
   }
}

* Algunas notas adicionales:

  1. No confíes en ocultar el título. A menudo hay un espacio vacío a pesar de que el título no se establece.
  2. No intente crear su propia vista con el pie de página del encabezado y la vista central. El encabezado, como se indicó anteriormente, puede no estar completamente oculto a pesar de solicitar FEATURE_NO_TITLE.
  3. No aplique mucho estilo a su vista de contenido con atributos de color o tamaño de texto. Deje que el diálogo se encargue de eso, de lo contrario corre el riesgo de poner texto negro en un diálogo azul oscuro porque el proveedor invirtió los colores.
Cocina
fuente
Originalmente publiqué setTitle () y setIcon () en el método onCreate (), pero la edición lo movió al método prepare () que se llama durante el método onPrepareDialog ().
Cookster
2
Gracias por compartir. Creo que la siguiente línea content = inflater.inflate(R.layout.custom_view, null);probablemente debería ser content = li.inflate(R.layout.custom_view, null);. Entonces, inflatertiene que ser reemplazado por li.
aLearner el
14

Estaba extendiendo un DialogFragment y la respuesta anterior no funcionó. Tuve que usar getDialog () para lograr eliminar el título:

getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
Argumento ilegal
fuente
@ojonugwaochalifu fue hace un tiempo, así que no recuerdo exactamente, pero estoy seguro de que debe hacerse antes del método setcontentView ()
Argumento ilegal
1
para cualquiera que tenga el mismo problema: agregué este código en onViewCreated ();
7geeky
2

¿El error no te dice exactamente qué está mal? Estás llamando requestWindowFeaturey setFeatureIntdespués de llamar setContentView.

Por cierto, ¿por qué llamas setContentViewdos veces?

EboMike
fuente
2

Para SDK versión 23 y superior, se genera la misma RuntimeException si está utilizando AppCompatActivity para extender su actividad. No sucederá si su actividad deriva directamente de Actividad.

Este es un problema conocido en Google como se menciona en https://code.google.com/p/android/issues/detail?id=186440

La solución provista para esto es usar el método supportRequestWindowFeature () en lugar de usar requestFeature ().

Vota a favor si resuelve tu problema.

Keshav Bansal
fuente
1

Cambie la versión del SDK de compilación , la versión del SDK de destino a la versión de Build Tools a 24.0.0 en build.gradle si tiene problemas en la solicitud.

Jaichander
fuente
0

En mi caso he mostrado DialogFragmenten Activity. En este fragmento de diálogo escribí como en DialogFragment eliminar borde negro :

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setStyle(STYLE_NO_FRAME, 0)
}

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
    super.onCreateDialog(savedInstanceState)

    val dialog = Dialog(context!!, R.style.ErrorDialogTheme)
    val inflater = LayoutInflater.from(context)
    val view = inflater.inflate(R.layout.fragment_error_dialog, null, false)
    dialog.setTitle(null)
    dialog.setCancelable(true)
    dialog.setContentView(view)
    return dialog
}

Quite setStyle(STYLE_NO_FRAME, 0)en onCreate()o / quitar chande onCreateDialog. Porque la configuración del cuadro de diálogo ha cambiado después de que se ha creado el cuadro de diálogo.

CoolMind
fuente
0

Tuve este problema con Dialogs basado en un DialogFragment extendido que funcionó bien en dispositivos que ejecutan API 26 pero falló con API 23. Las estrategias anteriores no funcionaron, pero resolví el problema eliminando el método onCreateView (que había sido agregado por más reciente plantilla de Android Studio) desde el DialogFragment y creando el diálogo en onCreateDialog.

BillC
fuente