requestFeature () должен быть вызван перед добавлением контента

135

Я пытаюсь реализовать пользовательский заголовок:

Вот мой класс Хелпер:

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

Вот где я называю это в onCreate ():

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

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

Но я получаю ошибку:

requestFeature() must be called before adding content
Шихан Алам
источник
Ответили здесь: stackoverflow.com/questions/16939814/…
карма

Ответы:

331

Ну, просто сделайте то, что говорит вам сообщение об ошибке.

Не звони setContentView()раньше requestFeature().

Примечание:

Как сказано в комментарии, для обоих ActionBarSherlockи AppCompatбиблиотеки, необходимо позвонить requestFeature()перед темsuper.onCreate()

Октавиан А. Дамиан
источник
60
блин, это классный ответ.
Человек
60
Для ActionBarSherlock также необходимо позвонить requestFeature()раньше super.onCreate(). Ссылка: github.com/JakeWharton/ActionBarSherlock/issues/…
Saran
1
Что если вам нужно показать один макет без строки заголовка, а затем показать один с строкой заголовка? Вы должны будете использовать, requestWindowFeature(Window.FEATURE_NO_TITLE)чтобы скрыть это, затем setContentView()для вашего первого макета, затем requestWindowFeature(Window.FEATURE_CUSTOM_TITLE)снова показать строку заголовка. Это было бы после setContentView()второго раза.
MSBG
35
Это тот же случай в AppCompat, что и @Saran. Вы должны позвонить requestFeatureдо этогоsuper.onCreate()
Джейсон Брукс
7
Этот ответ не сильно помогает ... но что я знаю
Оджонугва Джуд Очалифу
23

Я знаю, что ему больше года, но звонки requestFeature()так и не решили мою проблему. На самом деле я не называю это вообще.

Я полагаю, это была проблема с раздуванием взгляда. Несмотря на все мои поиски, я так и не нашел подходящего решения, пока не поигрался с разными методами надувания вида.

AlertDialog.Builder - это простое решение, но оно требует большой работы, если вы используете onPrepareDialog()для обновления этого представления.

Другой альтернативой является использование AsyncTask для диалогов.

Окончательное решение, которое я использовал ниже:

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

* Некоторые дополнительные примечания:

  1. Не полагайтесь на сокрытие названия. Часто там есть пустое место, несмотря на то, что заголовок не установлен.
  2. Не пытайтесь создать свой собственный вид с нижним колонтитулом и средним видом. Заголовок, как указано выше, не может быть полностью скрыт, несмотря на запрос FEATURE_NO_TITLE.
  3. Не используйте в качестве стиля представление содержимого с помощью цветовых атрибутов или размера текста. Позвольте диалогу справиться с этим, иначе вы рискуете поместить черный текст в темно-синий диалог, потому что поставщик инвертировал цвета.
Cookster
источник
Первоначально я разместил setTitle () и setIcon () в методе onCreate (), но редактирование переместило его в метод prepare (), который вызывается во время метода onPrepareDialog ().
Cookster
2
Спасибо, что поделился. Я думаю, что следующая строка, content = inflater.inflate(R.layout.custom_view, null);вероятно, должна быть content = li.inflate(R.layout.custom_view, null);. Итак, inflaterдолжен быть заменен на li.
aLearner
14

Я расширяю DialogFragment, и приведенный выше ответ не работает. Мне пришлось использовать getDialog (), чтобы добиться удаления заголовка:

getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
Незаконный аргумент
источник
@ojonugwaochalifu это было некоторое время назад, поэтому я точно не помню, но я уверен, что это нужно сделать перед методом setcontentView ()
Illegal Argument
1
для тех, кто сталкивается с той же проблемой: я добавил этот код в onViewCreated ();
7geeky
2

Разве ошибка не говорит точно, что не так? Ты звонишь requestWindowFeatureи setFeatureIntпосле звонкаsetContentView .

Кстати, почему ты звонишь setContentViewдважды?

EboMike
источник
2

Для SDK версии 23 и выше выдается то же исключение RuntimeException, если вы используете AppCompatActivity для расширения своей активности. Этого не произойдет, если ваша деятельность напрямую связана с деятельностью.

Это известная проблема в Google, упомянутая в https://code.google.com/p/android/issues/detail?id=186440.

Обходное решение, предусмотренное для этого, заключается в использовании метода supportRequestWindowFeature () вместо использования requestFeature ().

Пожалуйста, проголосуйте, если это решит вашу проблему.

Кешав Бансал
источник
1

Изменение версии SDK Compile , Target SDK версии для инструментов сборки версии для 24.0.0 в build.gradle если и сталкиваются проблемы в поиске Feature

Jaichander
источник
0

В моем случае я показал DialogFragmentв Activity. В этом фрагменте диалога я написал как в DialogFragment удалить черную рамку :

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
}

Либо удалить setStyle(STYLE_NO_FRAME, 0)в onCreate()или Chande / удалить onCreateDialog. Потому что настройки диалога изменились после того, как диалог был создан.

CoolMind
источник
0

У меня была эта проблема с диалогами, основанными на расширенном DialogFragment, который прекрасно работал на устройствах с API 26, но не работал с API 23. Вышеупомянутые стратегии не работали, но я решил проблему, удалив метод onCreateView (который был добавлен более недавний шаблон Android Studio) из DialogFragment и создания диалога в onCreateDialog.

BillC
источник