requestFeature () необхідно викликати перед додаванням вмісту


135

Я намагаюся реалізувати власну панель заголовків:

Ось мій клас 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);
        }
    }
}

Ось де я називаю це в 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

Відповіді:


331

Ну просто робіть те, що вам повідомляє повідомлення про помилку.

Не дзвоніть setContentView()раніше requestFeature().

Примітка:

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


60
чорт, це класна відповідь.
Людина

60
Для ActionBarSherlock також потрібно зателефонувати requestFeature()раніше super.onCreate(). Довідка: github.com/JakeWharton/ActionBarSherlock/isissue/…
Саран

1
Що робити, якщо вам потрібно показати один макет без заголовка, а потім показати його з рядком заголовка? Вам потрібно буде requestWindowFeature(Window.FEATURE_NO_TITLE)приховати його, потім setContentView()для першого макета, а потім requestWindowFeature(Window.FEATURE_CUSTOM_TITLE)знову показати рядок заголовка. Це було б після setContentView()другого разу.
msbg

35
Це той самий випадок в AppCompat, як сказав @Saran. Ви повинні зателефонувати requestFeatureранішеsuper.onCreate()
Джейсон Брукс

7
Ця відповідь не дуже допомагає ... але що я знаю
Ojonugwa Jude Ochalifu

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. Не стилізуйте перегляд вмісту за допомогою атрибутів кольору чи розміру тексту. Нехай діалогове вікно вирішить це, інші розумні ви ризикуєте помістити чорний текст у темно-синій діалог, оскільки постачальник перевернув кольори.

Спочатку я розмістив setTitle () та setIcon () у методі onCreate (), але правка перемістила його до методу prep (), який викликається під час методу onPrepareDialog ().
Кукстер

2
Дякую, що поділились. Я думаю, наступний рядок, content = inflater.inflate(R.layout.custom_view, null);мабуть, повинен бути content = li.inflate(R.layout.custom_view, null);. Отже, inflaterмає бути замінено на li.
aLearner

14

Я розширював діалоговий фрагмент, і вищевказана відповідь не працювала. Мені довелося використовувати getDialog (), щоб досягти видалення заголовка:

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

@ojonugwaochalifu був певний час назад, тому я точно не пам'ятаю, але я впевнений, що це потрібно зробити перед методом setcontentView ()
Незаконне аргументування

1
для будь-якого, хто стикається з тією ж проблемою: я додав цей код у onViewCreate ();
7geeky

2

Хіба помилка точно не говорить вам, що не так? Ти дзвониш requestWindowFeatureі setFeatureIntпісля дзвониш setContentView.

До речі, чому ти дзвониш setContentViewдвічі?


2

Для SDK версії 23 і вище, те саме RuntimeException викидається, якщо ви використовуєте AppCompatActivity для розширення своєї діяльності. Це не відбудеться, якщо ваша діяльність походить безпосередньо від діяльності.

Це відома проблема в Google, як згадується в https://code.google.com/p/android/isissue/detail?id=186440

Для цього передбачено використання методу supportRequestWindowFeature () замість використання requestFeature ().

Будь ласка, підкажіть, якщо це вирішить вашу проблему.


1

Зміна версії SDK Compile , Target SDK версії для інструментів збірки версії для 24.0.0 в build.gradle якщо і стикаються проблеми в пошуку Feature


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. Оскільки налаштування діалогу змінилися після створення діалогу.


0

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.