Menu in fragments android

Фрагменты

Существует два основных подхода в использовании фрагментов.

Первый способ основан на замещении родительского контейнера. Создаётся стандартная разметка и в том месте, где будут использоваться фрагменты, размещается контейнер, например, FrameLayout. В коде контейнер замещается фрагментом. При использовании подобного сценария в разметке не используется тег fragment, так как его нельзя менять динамически. Также вам придётся обновлять ActionBar, если он зависит от фрагмента. Здесь показан такой пример.

Второй вариант — используются отдельные разметки для телефонов и планшетов, которые можно разместить в разных папках ресурсов. Например, если в планшете используется двухпанельная разметка с двумя фрагментами на одной активности, мы используем эту же активность для телефона, но подключаем другую разметку, которая содержит один фрагмент. Когда нам нужно переключиться на второй фрагмент, то запускаем вторую активность.

Второй подход является наиболее гибким и в целом предпочтительным способом использования фрагментов. Активность проверяет в каком режиме (свои размеры) он запущен и использует разную разметку из ресурсов. Графически это выглядит следующим образом.

Основные классы

Сами фрагменты наследуются от androidx.fragment.app.Fragment. Существует подклассы фрагментов: ListFragment, DialogFragment, PreferenceFragment, WebViewFragment и др. Не исключено, что число классов будет увеличиваться, например, появился ещё один класс MapFragment.

Для взаимодействия между фрагментами используется класс android.app.FragmentManager — специальный менеджер по фрагментам.

Как в любом офисе, спецманагер не делает работу своими руками, а использует помощников. Например, для транзакций (добавление, удаление, замена) используется класс-помощник android.app.FragmentTransaction.

Для сравнения приведу названия классов из библиотеки совместимости:

  • android.support.v4.app.FragmentActivity
  • android.support.v4.app.Fragment
  • android.support.v4.app.FragmentManager
  • android.support.v4.app.FragmentTransaction

Как видите, разница в одном классе, который я привёл первым. Он используется вместо стандартного Activity, чтобы система поняла, что придётся работать с фрагментами. На данный момент студия создаёт проект на основе ActionBarActivity, который является подклассом FragmentActivity.

В одном приложении нельзя использовать новые фрагменты и фрагменты из библиотеки совместимости.

В 2018 году Гугл объявила фрагменты из пакета androd.app устаревшими. Заменяйте везде на версию из библиотеки совместимости. В 2020 году уже используют пакет androidx.fragment.app.

В версии Support Library 27.1.0 появились новые методы requireActivity() и requireContext(), которые пригодятся при написании кода, когда требуется наличие активности и нужно избежать ошибки на null.

Общий алгоритм работы с фрагментами будет следующим:

У каждого фрагмента должен быть свой класс. Класс наследуется от класса Fragment или схожих классов, о которых говорилось выше. Это похоже на создание новой активности или нового компонента.

Также, как в активности, вы создаёте различные методы типа onCreate() и т.д. Если фрагмент имеет разметку, то используется метод onCreateView() — считайте его аналогом метода setContentView(), в котором вы подключали разметку активности. При этом метод onCreateView() возвращает объект View, который является корневым элементом разметки фрагмента.

Разметку для фрагмента можно создать программно или декларативно через XML.

Создание разметки для фрагмента ничем не отличается от создания разметки для активности. Вот отрывок кода из метода onCreateView():

Глядя на этот код, вы должные понять, что фрагмент использует разметку из файла res/layout/first_fragment.xml, которая содержит кнопку с идентификатором android:id=»@+id/button_first». Здесь также прослеживается сходство с подключением компонентов в активности. Обратите внимание, что перед методом findViewById() используется view, так как этот метод относится к компоненту, а не к активности, как мы обычно делали в программах, когда просто опускали имя активности. Т.е. в нашем случае мы ищем ссылку на кнопку не среди разметки активности, а внутри разметки самого фрагмента.

Нужно помнить, что в методе inflate() последний параметр должен иметь значение false в большинстве случаев.

Читайте также:  Подключение андроид через usb как флешки

FragmentManager

Класс FragmentManager имеет два метода, позволяющих найти фрагмент, который связан с активностью:

findFragmentById(int id) Находит фрагмент по идентификатору findFragmentByTag(String tag) Находит фрагмент по заданному тегу

Методы транзакции

Мы уже использовали некоторые методы класса FragmentTransaction. Познакомимся с ними поближе

add() Добавляет фрагмент к активности remove() Удаляет фрагмент из активности replace() Заменяет один фрагмент на другой hide() Прячет фрагмент (делает невидимым на экране) show() Выводит скрытый фрагмент на экран detach() (API 13) Отсоединяет фрагмент от графического интерфейса, но экземпляр класса сохраняется attach() (API 13) Присоединяет фрагмент, который был отсоединён методом detach()

Методы remove(), replace(), detach(), attach() не применимы к статичным фрагментам.

Перед началом транзакции нужно получить экземпляр FragmentTransaction через метод FragmentManager.beginTransaction(). Далее вызываются различные методы для управления фрагментами.

В конце любой транзакции, которая может состоять из цепочки вышеперечисленных методов, следует вызвать метод commit().

Аргументы фрагмента

Фрагменты должны сохранять свою модульность и не должны общаться друг с другом напрямую. Если один фрагмент хочет докопаться до другого, он должен сообщить об этом своему менеджеру активности, а он уже передаст просьбу другому фрагменту. И наоборот. Это сделано специально для того, чтобы было понятно, что менеджер тут главный и он не зря зарплату получает. Есть три основных способа общения фрагмента с активностью.

  • Активность может создать фрагмент и установить аргументы для него
  • Активность может вызвать методы экземпляра фрагмента
  • Фрагмент может реализовать интерфейс, который будет использован в активности в виде слушателя

Фрагмент должен иметь только один пустой конструктор без аргументов. Но можно создать статический newInstance с аргументами через метод setArguments().

Доступ к аргументам можно получить в методе onCreate() фрагмента:

Динамически загружаем фрагмент в активность.

Если активность должна выполнить какую-то операцию в фрагменте, то самый простой способ — задать нужный метод в фрагменте и вызвать данный метод через экземпляр фрагмента.

Вызываем метод в активности:

Если фрагмент должен сообщить о своих действиях активности, то следует реализовать интерфейс.

Управление стеком фрагментов

Фрагменты, как и активности, могут управляться кнопкой Back. Вы можете добавить несколько фрагментов, а потом через кнопку Back вернуться к первому фрагменту. Если в стеке не останется ни одного фрагмента, то следующее нажатие кнопки закроет активность.

Чтобы добавить транзакцию в стек, вызовите метод FragmentTransaction.addToBackStack(String) перед завершением транзакции (commit). Строковый аргумент — опциональное имя для идентификации стека или null. Класс FragmentManager имеет метод popBackStack(), возвращающий предыдущее состояние стека по этому имени.

Если вы вызовете метод addToBackStack() при удалении или замещении фрагмента, то будут вызваны методы фрагмента onPause(), onStop(), onDestroyView().

Когда пользователь нажимает на кнопку возврата, то вызываются методы фрагмента onCreateView(), onActivityCreated(), onStart() и onResume().

Рассмотрим пример реагирования на кнопку Back в фрагменте без использования стека. Активность имеет метод onBackPressed(), который реагирует на нажатие кнопки. Мы можем в этом методе сослаться на нужный фрагмент и вызвать метод фрагмента.

Теперь в классе фрагмента прописываем метод с нужным кодом.

Более желательным вариантом является использование интерфейсов. В некоторых примерах с фрагментами такой приём используется.

Интеграция Action Bar/Options Menu

Фрагменты могут добавлять свои элементы в панель действий или меню активности. Сначала вы должны вызвать метод Fragment.setHasOptionsMenu() в методе фрагмента onCreate(). Затем нужно задать настройки для методов фрагмента onCreateOptionsMenu() и onOptionsItemSelected(), а также при необходимости для методов onPrepareOptionsMenu(), onOptionsMenuClosed(), onDestroyOptionsMenu(). Работа методов фрагмента ничем не отличается от аналогичных методов для активности.

В активности, которая содержит фрагмент, данные методы автоматически сработают.

Если активность содержит собственные элементы панели действий или меню, то следует позаботиться, чтобы они не мешали вызовам методам фрагментов.

Код для активности:

Код для фрагмента:

Связь между фрагментом и активностью

Экземпляр фрагмента связан с активностью. Активность может вызывать методы фрагмента через ссылку на объект фрагмента. Доступ к фрагменту можно получить через методы findFragmentById() или findFragmentByTag().

Источник

Android Fragment Menu Example

Fragment can has it’s own menu, the fragment menu items are also displayed in android application action bar. This article will show you how to add menu items in android fragment and how to use fragment menu items with activity menu items.

Читайте также:  Panzer general для android

1. How To Add Menu Items For Android Fragment.

  1. Create a fragment menu items layout xml file. You can read article Android Actionbar Example for more detail.
  2. Override Fragment class onCreate(@Nullable Bundle savedInstanceState) method, set hasOptionsMenu to true.
  3. Override Fragment class onCreateOptionsMenu(Menu menu, MenuInflater inflater) method, inflate the fragment menu layout xml file in this method as below.

2. How To Handle Fragment Menu Item Click Event.

You can override Fragment class’s onOptionsItemSelected(MenuItem item) method to handle Fragment menu item click event like below.

Activity also have onOptionsItemSelected(MenuItem item) method. When you click a menu item, no matter where the menu item exist ( fragment or activity), activity and fragment will all trigger this method.

So you need to add code in this method to check which menu item is clicked.

3. How To Make Fragment Menu Items Order First In Action Bar.

If both your activity and fragments all has their own menu items. All the menu items will be displayed in the action bar.

But when you open a fragment in activity, of course you want fragment menu items order first than activity menu items, this can make it user friendly.

To implement this, you need to set android:orderInCategory attribute value for each menu items in all the menu layout xml file. The menu item with small value will order first in the action bar.

But when you hide or detach the fragment, the fragment menu items will disappear from the action bar also.

4. Android Fragment Menu Items Example.

If you can not watch the above video, you can see it on the youtube URL https://youtu.be/pOhURXCTXu8

  1. In this example there is a fragment and a activity. Each has their own menu items.
  2. When the activity start, you can see the activity menu items.
  3. When you click the show button to open a fragment, you can see the fragment menu items ordered before activity menu items. This is because of the menu item’s android:orderInCategory attribute value.
  4. When you click the hide button to hide the fragment. The fragment menu items disappear from the action bar also.
  5. You can also click back menu to exit the fragment and the activity. Because we have add the fragment in the back stack.

5. Example Source Code.

Main Layout Xml File.

This is the activity layout xml file.

Fragment Layout Xml File.

This is the fragment layout xml file.

Activity Menu Items Xml File.

Saved in app / res / menu folder.

Fragment Menu Items Xml File.

Источник

Меню опций Android во фрагменте

Я пытаюсь добавить элемент в меню «Параметры» из группы фрагментов.

Я создал новый MenuFragment class и расширил это для фрагментов, в которые я хочу включить пункт меню. Вот код:

почему-то onCreateOptionsMenu Кажется, не запускается.

19 ответов

вызовите метод super:

поместите инструкции журнала в код, чтобы узнать, не вызывается ли метод или меню не изменяется вашим кодом.

также убедитесь, что вы звоните SetHasOptionsMenu на onCreate чтобы уведомить фрагмент, что он должен участвовать в обработке меню опций.

у меня была та же проблема, но я думаю, что лучше подвести итог и ввести последний шаг, чтобы заставить его работать:

добавить метод setHasOptionsMenu (true)в onCreate(Bundle savedInstanceState) метод.

переопределить onCreateOptionsMenu(Menu menu, MenuInflater inflater) (Если вы хотите сделать что-то другое в меню фрагмента) и onOptionsItemSelected(MenuItem item) методы в вашем фрагменте.

внутри onOptionsItemSelected(MenuItem item) метод действия, убедитесь, что вы возвращаете false, когда пункт меню действие будет реализовано в onOptionsItemSelected(MenuItem item) метод фрагмента.

активность

фрагмент

Если вы найдете onCreateOptionsMenu(Menu menu, MenuInflater inflater) метод не вызывается, убедитесь, что вы звоните следующей из фрагмента onCreate(Bundle savedInstanceState) способ:

Читайте также:  Анализ звука для андроид

В моем случае, мне нужно меню, чтобы обновить webview внутри определенного фрагмента, для этого я использовал:

фрагмент:

меню «Файл».в XML

на menu.xml вы должны добавить все пункты меню. Затем вы можете скрыть элементы, которые вы не хотите видеть в исходной загрузки.

добавить setHasOptionsMenu(true) в методе onCreate () для вызова элементов меню в вашем классе фрагментов.

FragmentClass.java

вам не нужно переопределять onCreateOptionsMenu в вашем классе фрагментов снова. Пункты меню можно изменить (добавить/удалить) путем переопределения onPrepareOptionsMenu метод доступен во фрагменте.

вам нужно использовать меню.очистить () перед раздуванием меню.

В моем случае, вот шаги.

Шаг 1

Шаг 2

Шаг 3

У меня была такая же проблема, мои фрагменты страницы ViewPager. Причина этого заключалась в том, что при создании экземпляра FragmentPagerAdapter я использовал child fragment manager, а не activity support fragment manager.

Если вы хотите добавить свое меню custom

ваш код в порядке. В методе отсутствовал только супер:

Я сходил с ума, потому что ни один из ответов здесь не работал для меня.

чтобы показать меню, я должен был позвонить: setSupportActionBar(toolbar)

Примечание: Если ваш toolbar view не находится в том же макете активности, который вы не можете использовать вызов выше непосредственно из класса activity, в этом случае вам нужно будет получить эту активность из класса fragment, а затем вызвать setSupportActionBar(toolbar) . Запоминание: ваш класс activity должен расширять AppCompatActivity.

надеемся, что этот ответ поможет вам.

TL; DR

использовать android.support.v7.widget.Toolbar и вобще:

Автономная Панель Инструментов

большинство предлагаемых решений, таких как setHasOptionsMenu(true) работают только тогда, когда родительская активность имеет панель инструментов в своем макете и объявляет его через setSupportActionBar() . Тогда фрагменты могут участвовать в населении меню этого точного ActionBar:

фрагмент.onCreateOptionsMenu (): инициализация содержимого Меню стандартных опций хоста фрагментов.

если вы хотите отдельную панель инструментов и меню для одного конкретного фрагмента вы можете сделать следующее:

Да, это так просто. Вам даже не нужно переопределять onCreate() или onCreateOptionsMenu() .

PS: это работает только с android.support.v4.app.Fragment и android.support.v7.widget.Toolbar (также обязательно используйте AppCompatActivity и AppCompat темы в своем styles.xml ).

настройка меню параметров после создания вида фрагмента работала хорошо для меня.

моя проблема была немного другая. Я все сделал правильно. Но я унаследовал неправильный класс для действия, в котором находится фрагмент.

чтобы быть ясным, если вы переопределяете onCreateOptionsMenu(Menu menu, MenuInflater inflater) во фрагменте убедитесь, что класс activity, в котором размещен этот фрагмент, наследует android.support.v7.app.ActionBarActivity (в случае, если вы хотите поддерживать ниже уровня API 11).

я унаследовал android.support.v4.app.FragmentActivity для поддержки уровня API ниже 11.

одну вещь я бы добавил к этому и причину, по которой это не работало для меня.

это похоже на ответ Napster.

убедитесь, что активность хостинга вашего фрагмента расширяется AppCompatActivity , а не FragmentActivity !

из ссылки Google документация для FragmentActivity:

Примечание: Если вы хотите реализовать действие, которое включает в себя панель действий, вместо этого следует использовать класс ActionBarActivity, который является подклассом этого класса, позволяет использовать API фрагментов на уровне API 7 и выше.

чтобы обновить ответ Napster — ActionBarActivity теперь, будучи устаревшим, используйте AppCompatActivity вместо.

при использовании AppCompatActivity , также убедитесь, что вы установили «тема деятельности Theme.AppCompat или аналогичная тема» (Google Doc).

Примечание: android.support.v7.app.AppCompatActivity является наследником android.support.v4.app.FragmentActivity класса (см. AppCompatActivity ref doc).

в папке меню сделать .меню XML-файл и добавить этот XML

в вашем классе фрагментов переопределите этот метод и

Теперь просто настройте xml-файл меню в классе фрагментов

Если все вышеперечисленное не работает, вам нужно отладить и убедиться, что функция onCreateOptionsMenu была вызвана (путем размещения журнала отладки или записи. )

если он не запущен, возможно, ваша тема Android не поддерживает панель действий. Открываем AndroidManifest.xml и установите значение для android:theme с темой поддержки панели действий:

на onCreate метод add setHasOptionMenu ()

затем переопределить код onCreateOptionsMenu

Источник

Оцените статью