2010-11-22 15 views
114

Próbuję zaimplementować niestandardowy pasek tytułowy:requestFeature() musi być wywołana przed dodaniem zawartości

Oto moja klasa Pomocnik:

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

Oto gdzie ja to nazywam w onCreate():

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

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

Ale pojawia się błąd:

requestFeature() must be called before adding content 
+0

tutaj odpowiedzi: http://stackoverflow.com/questions/16939814/android-util-androidruntimeexception-requestfeature-must-be-called-before-add – user3167086

Odpowiedz

297

Cóż, po prostu rób to, co mówi komunikat o błędzie. Nie należy dzwonić pod numer setContentView() przed requestFeature().

Uwaga:

Jak powiedział w komentarzach, zarówno ActionBarSherlock i AppCompat biblioteki, trzeba zadzwonić requestFeature() przed super.onCreate()

+58

Cholera, to jest klasyczna odpowiedź. –

+58

Dla ActionBarSherlock konieczne jest również wywołanie 'requestFeature()' przed 'super.onCreate()'. Odsyłacz: https://github.com/JakeWharton/ActionBarSherlock/issues/310#issuecomment-7350074 – Saran

+1

Co zrobić, jeśli chcesz wyświetlić jeden układ bez paska tytułu, a następnie pokazać go z paskiem tytułu? Będziesz musiał użyć 'requestWindowFeature (Window.FEATURE_NO_TITLE), aby ją ukryć, następnie' setContentView() 'dla twojego pierwszego układu, następnie' requestWindowFeature (Window.FEATURE_CUSTOM_TITLE) 'aby ponownie wyświetlić pasek tytułu. To byłoby po 'setContentView()' po raz drugi. – msbg

2

Czy błąd nie mówi dokładnie, co jest nie tak? Dzwonisz pod numer requestWindowFeature i setFeatureInt po zadzwonieniu pod numer setContentView.

Przy okazji, dlaczego dzwonisz pod numer setContentView dwa razy?

20

wiem, że to ponad rok, ale nazywając requestFeature() nigdy rozwiązać mój problem . W rzeczywistości wcale tego nie nazywam.

To był problem z nadmuchiwaniem widoku, jak sądzę. Pomimo wszystkich moich poszukiwań, nigdy nie znalazłem odpowiedniego rozwiązania, dopóki nie bawiłem się różnymi metodami nadmuchiwania widoku.

AlertDialog.Builder jest prostym rozwiązaniem, ale wymaga wiele pracy, jeśli używasz onPrepareDialog() do aktualizacji tego widoku.

Inną alternatywą jest wykorzystanie AsyncTask do okien dialogowych.

Ostateczne rozwiązanie, które użyłem jest poniżej:

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

* Niektóre Dodatkowe uwagi:

  1. nie opierają się na ukrywanie tytuł. Często, mimo że tytuł nie jest ustawiony, często jest pusta przestrzeń.
  2. Nie próbuj budować własnego widoku ze stopką nagłówka i środkowym widokiem. Nagłówek, jak wspomniano powyżej, może nie być całkowicie ukryty, mimo prośby FEATURE_NO_TITLE.
  3. Nie należy silnie stylizować widoku treści za pomocą atrybutów kolorów lub rozmiaru tekstu. Niech dialog sobie z tym poradzi, w przeciwnym razie ryzykujesz umieszczenie czarnego tekstu na ciemnoniebieskim oknie dialogowym, ponieważ sprzedawca odwrócił kolory.
+0

Pierwotnie napisałem setTitle() i setIcon() w metodzie onCreate(), ale edycja przeniosła je do metody prepare(), która jest wywoływana podczas metody onPrepareDialog(). – Cookster

+2

Dzięki za udostępnienie. Myślę, że następujący wiersz 'content = inflater.inflate (R.layout.custom_view, null); prawdopodobnie powinien być' content = li.inflate (R.layout.custom_view, null); '. Tak więc, 'inflater' musi zostać zastąpione przez' li'. – aLearner

10

Byłem rozszerzenie DialogFragment i powyższa odpowiedź nie działa.Musiałem użyć getDialog(), aby osiągnąć usunąć tytuł:

getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE); 
+0

Skąd dodałeś ten kod? –

+0

@ojonugwaochalifu to był jakiś czas temu, więc nie pamiętam dokładnie, ale jestem pewien, że musi to być zrobione przed setcontentView() metoda –

+0

dla każdego z tym samym problem: Dodałem ten kod w onViewCreated(); – 7geeky

1

przypadku SDK w wersji 23 i powyżej, ta sama RuntimeException jest wyrzucane, jeśli używasz AppCompatActivity rozszerzyć swoją działalność. Nie stanie się tak, jeśli twoja aktywność wywodzi się bezpośrednio z działania.

ten jest znanym problemem w google jak wspomniano w https://code.google.com/p/android/issues/detail?id=186440

Obejściem przewidziane jest użycie supportRequestWindowFeature() Metoda zamiast stosowania requestFeature().

Proszę załatwić sprawę, jeśli rozwiąże ona problem.

1

Zmiana kompilacji SDK wersja, wersja docelowa wersja SDK do Zbuduj Narzędzia do 24.0.0 w build.gradle jeśli u obliczu problemu w żądaniu Feature

Powiązane problemy