requestFeature () doit être appelée avant d'ajouter du contenu

135

J'essaye d'implémenter une barre de titre personnalisée:

Voici ma classe Helper:

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

Voici où je l'appelle dans onCreate ():

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

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

Mais j'obtiens l'erreur:

requestFeature() must be called before adding content
Sheehan Alam
la source

Réponses:

331

Eh bien, faites simplement ce que le message d'erreur vous indique.

N'appelez pas setContentView()avant requestFeature().

Remarque:

Comme indiqué dans les commentaires, pour les deux ActionBarSherlocket la AppCompatbibliothèque, il est nécessaire d'appeler requestFeature()avantsuper.onCreate()

Octavian A. Damiean
la source
60
putain, c'est une réponse élégante.
A Person
60
Pour ActionBarSherlock, il est également nécessaire d'appeler requestFeature()avant super.onCreate(). Référence: github.com/JakeWharton/ActionBarSherlock/issues/…
Saran
1
Que faire si vous devez afficher une mise en page sans barre de titre, puis en afficher une avec une barre de titre? Vous devrez utiliser requestWindowFeature(Window.FEATURE_NO_TITLE)pour le masquer, puis setContentView()pour votre première mise en page, puis requestWindowFeature(Window.FEATURE_CUSTOM_TITLE)pour afficher à nouveau la barre de titre. Ce serait après setContentView()la deuxième fois.
msbg
35
C'est le même cas dans AppCompat que @Saran l'a dit. Vous devez appeler votre requestFeatureavantsuper.onCreate()
Jaison Brooks
7
Cette réponse n'aide pas beaucoup ... mais que sais-je
Ojonugwa Jude Ochalifu
23

Je sais qu'il a plus d'un an, mais appeler requestFeature()n'a jamais résolu mon problème. En fait, je ne l'appelle pas du tout.

C'était un problème pour gonfler la vue, je suppose. Malgré toutes mes recherches, je n'ai jamais trouvé de solution appropriée jusqu'à ce que je joue avec les différentes méthodes pour gonfler une vue.

AlertDialog.Builder est la solution simple mais nécessite beaucoup de travail si vous utilisez onPrepareDialog()pour mettre à jour cette vue.

Une autre alternative consiste à utiliser AsyncTask pour les dialogues.

Une solution finale que j'ai utilisée est ci-dessous:

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

* Quelques notes supplémentaires:

  1. Ne comptez pas sur le fait de cacher le titre. Il y a souvent un espace vide bien que le titre ne soit pas défini.
  2. N'essayez pas de créer votre propre vue avec le pied de page d'en-tête et la vue du milieu. L'en-tête, comme indiqué ci-dessus, peut ne pas être entièrement masqué malgré la demande de FEATURE_NO_TITLE.
  3. Ne stylisez pas fortement votre affichage de contenu avec des attributs de couleur ou une taille de texte. Laissez la boîte de dialogue gérer cela, sinon vous risquez de mettre du texte noir sur une boîte de dialogue bleu foncé parce que le fournisseur a inversé les couleurs.
Cookster
la source
À l'origine, j'ai publié setTitle () et setIcon () dans la méthode onCreate (), mais la modification l'a déplacé vers la méthode prepare () qui est appelée pendant la méthode onPrepareDialog ().
Cookster
2
Merci d'avoir partagé. Je pense que la ligne suivante content = inflater.inflate(R.layout.custom_view, null);devrait probablement l'être content = li.inflate(R.layout.custom_view, null);. Donc, inflaterdoit être remplacé par li.
aLearner
14

J'étendais un DialogFragment et la réponse ci-dessus n'a pas fonctionné. J'ai dû utiliser getDialog () pour supprimer le titre:

getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
Argument illégal
la source
@ojonugwaochalifu il y a quelque temps, donc je ne me souviens pas exactement mais je suis sûr que cela doit être fait avant la méthode setcontentView ()
Argument illégal
1
pour toute personne confrontée au même problème: j'ai ajouté ce code dans onViewCreated ();
7geeky du
2

L'erreur ne vous dit-elle pas exactement ce qui ne va pas? Vous appelez requestWindowFeatureet setFeatureIntaprès avoir appelé setContentView.

Au fait, pourquoi appelez-vous setContentViewdeux fois?

EboMike
la source
2

Pour SDK version 23 et supérieure, la même RuntimeException est levée si vous utilisez AppCompatActivity pour étendre votre activité. Cela ne se produira pas si votre activité découle directement de l'activité.

Il s'agit d'un problème connu sur Google, comme mentionné dans https://code.google.com/p/android/issues/detail?id=186440

Le contournement fourni pour cela consiste à utiliser la méthode supportRequestWindowFeature () au lieu d'utiliser requestFeature ().

Veuillez voter pour si cela résout votre problème.

Keshav Bansal
la source
1

Changer la Version Compile SDK , SDK version cible à Outils de compilation dont à 24.0.0 dans build.gradle si u face à problème dans la demande Fonction

Jaichander
la source
0

Dans mon cas , je l' ai montré DialogFragmentdans Activity. Dans ce fragment de dialogue, j'ai écrit comme dans DialogFragment supprimer la bordure noire :

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
}

Soit remove setStyle(STYLE_NO_FRAME, 0)in, onCreate()soit chande / remove onCreateDialog. Parce que les paramètres de la boîte de dialogue ont changé après la création de la boîte de dialogue.

CoolMind
la source
0

J'ai eu ce problème avec les dialogues basés sur un DialogFragment étendu qui fonctionnait bien sur les appareils exécutant l'API 26 mais a échoué avec l'API 23. Les stratégies ci-dessus n'ont pas fonctionné mais j'ai résolu le problème en supprimant la méthode onCreateView (qui avait été ajoutée par un plus récent modèle Android Studio) à partir de DialogFragment et création de la boîte de dialogue dans onCreateDialog.

BillC
la source