requestFeature () muss vor dem Hinzufügen von Inhalten aufgerufen werden

135

Ich versuche, eine benutzerdefinierte Titelleiste zu implementieren:

Hier ist meine Helferklasse:

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

Hier rufe ich es in onCreate () auf:

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

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

Aber ich bekomme den Fehler:

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

Antworten:

330

Tun Sie einfach, was Ihnen die Fehlermeldung sagt.

Rufen Sie nicht setContentView()vorher an requestFeature().

Hinweis:

Wie in den Kommentaren gesagt, für beide ActionBarSherlockund AppCompatBibliothek, ist es notwendig , nennen requestFeature()vorsuper.onCreate()

Octavian A. Damiean
quelle
60
Verdammt, das ist eine noble Antwort.
Eine Person
60
Für ActionBarSherlock ist es auch erforderlich, requestFeature()vorher aufzurufen super.onCreate(). Referenz: github.com/JakeWharton/ActionBarSherlock/issues/…
Saran
1
Was ist, wenn Sie ein Layout ohne Titelleiste und dann eines mit Titelleiste anzeigen müssen? Sie müssen es requestWindowFeature(Window.FEATURE_NO_TITLE)ausblenden, dann setContentView()für Ihr erstes Layout und dann requestWindowFeature(Window.FEATURE_CUSTOM_TITLE)die Titelleiste wieder anzeigen. Das wäre nach setContentView()dem zweiten Mal.
msbg
35
Es ist der gleiche Fall in AppCompat wie bei @Saran. Sie müssen Ihre requestFeaturevorher anrufensuper.onCreate()
Jaison Brooks
7
Diese Antwort hilft nicht viel ... aber was weiß ich
Ojonugwa Jude Ochalifu
23

Ich weiß, dass es über ein Jahr alt ist, aber das Anrufen requestFeature()hat mein Problem nie gelöst. Tatsächlich nenne ich es überhaupt nicht.

Ich nehme an, es war ein Problem, die Sicht aufzublähen. Trotz all meiner Suche habe ich nie eine geeignete Lösung gefunden, bis ich mit den verschiedenen Methoden zum Aufblasen einer Ansicht herumgespielt habe.

AlertDialog.Builder ist die einfache Lösung, erfordert jedoch viel Arbeit, wenn Sie diese onPrepareDialog()zum Aktualisieren dieser Ansicht verwenden.

Eine andere Alternative besteht darin, AsyncTask für Dialoge zu nutzen.

Eine endgültige Lösung, die ich verwendet habe, ist unten:

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

* Einige zusätzliche Hinweise:

  1. Verlasse dich nicht darauf, den Titel zu verstecken. Es gibt oft ein leeres Feld, obwohl der Titel nicht festgelegt ist.
  2. Versuchen Sie nicht, eine eigene Ansicht mit Kopf- und Mittelansicht zu erstellen. Der Header kann, wie oben angegeben, trotz Anforderung von FEATURE_NO_TITLE möglicherweise nicht vollständig ausgeblendet werden.
  3. Gestalten Sie Ihre Inhaltsansicht nicht stark mit Farbattributen oder Textgröße. Lassen Sie den Dialog damit umgehen, andernfalls riskieren Sie, schwarzen Text in einen dunkelblauen Dialog zu setzen, da der Anbieter die Farben invertiert hat.
Kocher
quelle
Ursprünglich habe ich setTitle () und setIcon () in der onCreate () -Methode gepostet, aber die Bearbeitung hat sie in die prepare () -Methode verschoben, die während der onPrepareDialog () -Methode aufgerufen wird.
Cookster
2
Danke für das Teilen. Ich denke, die folgende Zeile content = inflater.inflate(R.layout.custom_view, null);sollte wahrscheinlich sein content = li.inflate(R.layout.custom_view, null);. Muss inflateralso durch ersetzt werden li.
aLearner
14

Ich habe ein DialogFragment erweitert und die obige Antwort hat nicht funktioniert. Ich musste getDialog () verwenden, um den Titel zu entfernen:

getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
Illegales Argument
quelle
@ojonugwaochalifu es ist eine Weile her, also erinnere ich mich nicht genau, aber ich bin sicher, dass es vor der setcontentView () -Methode getan werden muss
Illegales Argument
1
für alle, die vor dem gleichen Problem stehen: Ich habe diesen Code in onViewCreated () hinzugefügt.
7geeky
2

Sagt Ihnen der Fehler nicht genau, was falsch ist? Sie rufen an requestWindowFeatureund setFeatureIntnachdem Sie angerufen haben setContentView.

Warum rufst du übrigens setContentViewzweimal an?

EboMike
quelle
2

Ab SDK Version 23 wird dieselbe RuntimeException ausgelöst, wenn Sie AppCompatActivity zum Erweitern Ihrer Aktivität verwenden. Es wird nicht passieren, wenn Ihre Aktivität direkt von Aktivität abgeleitet ist.

Dies ist ein bekanntes Problem bei Google, wie unter https://code.google.com/p/android/issues/detail?id=186440 erwähnt

Die dafür vorgesehene Problemumgehung besteht darin, die supportRequestWindowFeature () -Methode anstelle von requestFeature () zu verwenden.

Bitte stimmen Sie ab, wenn es Ihr Problem löst.

Keshav Bansal
quelle
1

Ändern Sie die Compile SDK-Version und die Target SDK-Version in Build Tools auf 24.0.0 in build.gradle, wenn Sie Probleme mit der Anforderungsfunktion haben

Jaichander
quelle
0

In meinem Fall habe ich gezeigt , DialogFragmentin Activity. In diesem Dialogfragment, das ich wie in DialogFragment geschrieben habe, entfernen Sie den schwarzen Rand :

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
}

Entweder entfernen setStyle(STYLE_NO_FRAME, 0)in onCreate()oder chande / entfernen onCreateDialog. Weil sich die Dialogeinstellungen geändert haben, nachdem der Dialog erstellt wurde.

CoolMind
quelle
0

Ich hatte dieses Problem mit Dialogen, die auf einem erweiterten DialogFragment basierten, das auf Geräten mit API 26 einwandfrei funktionierte, aber mit API 23 fehlschlug. Die oben genannten Strategien funktionierten nicht, aber ich löste das Problem, indem ich die onCreateView-Methode entfernte (die durch eine weitere hinzugefügt wurde aktuelle Android Studio-Vorlage) aus dem DialogFragment und Erstellen des Dialogfelds in onCreateDialog.

BillC
quelle