В этом уроке:

- программно размещаем элементы в ActionBar
- используем элементы из фрагментов

 

Недавно на форуме был вопрос о том, как во время работы программы менять содержимое ActionBar. Тема действительно интересная, и незаслуженно мною пропущенная. В этом уроке будем с ней разбираться.

Опробуем три способа работы с элементами:

1) Добавление/удаление MenuItem в объект Menu

2) Показ/скрытие группы в Menu

3) Элементы, относящиеся к фрагментам

С первыми двумя пунктами все понятно, эти механизмы мы рассматривали еще в Уроке 14.

Более интересен третий пункт. Фрагмент может реализовать в себе метод onCreateOptionsMenu и, тем самым, создать свои элементы для ActionBar. Как только фрагмент будет добавлен на экран, эти элементы добавятся в ActionBar. А когда фрагмент с экрана уберут, элементы исчезнут.

Создадим приложение, которое реализует три этих варианта.

 

Создадим проект:

Project name: P1121_DynamicActionBar
Build Target: Android 4.1
Application name: DynamicActionBar
Package name: ru.startandroid.develop.p1121dynamicactionbar
Create Activity: MainActivity

 

Добавим строки в strings.xml:

<string name="add_del">Добавить/удалить</string>
<string name="visible">Показать/скрыть</string>
<string name="fragment">Фрагмент</string>
<string name="frag1_text">Fragment 1</string>
<string name="frag2_text">Fragment 2</string>
<string name="menu_item1">Item 1</string>
<string name="menu_item2">Item 2</string>
<string name="menu_item31">Item 31</string>
<string name="menu_item32">Item 32</string>

 

Создадим два фрагмента. Начнем с layout-файлов.

fragment1.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
	xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_width="match_parent"
	android:layout_height="match_parent"
	android:background="#77ff0000"
	android:orientation="vertical">
	<TextView
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:text="@string/frag1_text">
	</TextView>
</LinearLayout>

 

fragment2.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
	xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_width="match_parent"
	android:layout_height="match_parent"
	android:background="#7700ff00"
	android:orientation="vertical">
	<TextView
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:text="@string/frag2_text">
	</TextView>
</LinearLayout>

 

Файлы с пунктами меню (они же - элементы ActionBar):

res/menu/fragment1.xml:

<?xml version="1.0" encoding="utf-8"?>
<menu
	xmlns:android="http://schemas.android.com/apk/res/android">
	<item
		android:id="@+id/frag1_item"
		android:icon="@android:drawable/ic_dialog_info"
		android:showAsAction="ifRoom|withText"
		android:title="@string/menu_item31">
	</item>
</menu>

 

res/menu/fragment2.xml:

<?xml version="1.0" encoding="utf-8"?>
<menu
	xmlns:android="http://schemas.android.com/apk/res/android">
	<item
		android:id="@+id/frag2_item"
		android:icon="@android:drawable/ic_dialog_email"
		android:showAsAction="ifRoom|withText"
		android:title="@string/menu_item32">
	</item>
</menu>

По одному элементу для каждого фрагмента. Эти элементы будут появляться в ActionBar при выводе фрагмента на экран.

 

Классы.

Fragment1.java:

package ru.startandroid.develop.p1121dynamicactionbar;

import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
import android.view.ViewGroup;

public class Fragment1 extends Fragment {

  public void onCreate(Bundle savedInstanceState) {
    setHasOptionsMenu(true);
    super.onCreate(savedInstanceState);
  }

  public View onCreateView(LayoutInflater inflater, ViewGroup container,
      Bundle savedInstanceState) {
    return inflater.inflate(R.layout.fragment1, null);
  }

  public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.fragment1, menu);
    super.onCreateOptionsMenu(menu, inflater);
  }

}

 

Fragment2.java:

package ru.startandroid.develop.p1121dynamicactionbar;

import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
import android.view.ViewGroup;

public class Fragment2 extends Fragment {
  
  public void onCreate(Bundle savedInstanceState) {
    setHasOptionsMenu(true);
    super.onCreate(savedInstanceState);
  }
  
  public View onCreateView(LayoutInflater inflater, ViewGroup container,
      Bundle savedInstanceState) {
    return inflater.inflate(R.layout.fragment2, null);
  }
  
  public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.fragment2, menu);
    super.onCreateOptionsMenu(menu, inflater);
  }

}

В onCreate с помощью setHasOptionsMenu включаем режим вывода элементов фрагмента в ActionBar.

В onCreateView создаем View, в onCreateOptionsMenu – меню. Все как обычно.

Фрагменты готовы.

 

Теперь займемся Activity. Перепишем res/layout/main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
	xmlns:android="http://schemas.android.com/apk/res/android"
	xmlns:tools="http://schemas.android.com/tools"
	android:id="@+id/LinearLayout1"
	android:layout_width="match_parent"
	android:layout_height="match_parent"
	android:orientation="vertical">
	<CheckBox
		android:id="@+id/chbAddDel"
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:onClick="onClick"
		android:text="@string/add_del">
	</CheckBox>
	<CheckBox
		android:id="@+id/chbVisible"
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:onClick="onClick"
		android:text="@string/visible">
	</CheckBox>
	<Button
		android:id="@+id/btnFrag"
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:onClick="onClick"
		android:text="@string/fragment">
	</Button>
	<FrameLayout
		android:id="@+id/cont"
		android:layout_width="match_parent"
		android:layout_height="match_parent">
	</FrameLayout>
</LinearLayout>

Два чекбокса и кнопка. Чекбоксы отвечают за работу с элементами с помощью первого и второго способов. Кнопка будет показывать поочередно два фрагмента в контейнере cont.

 

res/menu/main.xml:

<?xml version="1.0" encoding="utf-8"?>
<menu
	xmlns:android="http://schemas.android.com/apk/res/android">
	<group
		android:id="@+id/groupVsbl">
		<item
			android:id="@+id/item2"
			android:icon="@android:drawable/ic_menu_call"
			android:showAsAction="always|withText"
			android:title="@string/menu_item2">
		</item>
	</group>
</menu>

Создаем группу, а в ней элемент. Эту группу будем скрывать и показывать.

 

MainActivity.java:

package ru.startandroid.develop.p1121dynamicactionbar;

import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.CheckBox;

public class MainActivity extends Activity {

  final int MENU_ID = 1;

  CheckBox chbAddDel;
  CheckBox chbVisible;

  Fragment frag1;
  Fragment frag2;
  Fragment frag;

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    chbAddDel = (CheckBox) findViewById(R.id.chbAddDel);
    chbVisible = (CheckBox) findViewById(R.id.chbVisible);

    frag = frag1 = new Fragment1();
    frag2 = new Fragment2();

  }

  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.main, menu);
    menu.setGroupVisible(R.id.groupVsbl, chbVisible.isChecked());
    if (chbAddDel.isChecked()) {
      menu.add(0, MENU_ID, 0, R.string.menu_item1)
          .setIcon(android.R.drawable.ic_delete)
          .setShowAsAction(
              MenuItem.SHOW_AS_ACTION_ALWAYS
                  | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
    } else {
      menu.removeItem(MENU_ID);
    }
    return true;
  }

  public void onClick(View view) {
    switch (view.getId()) {
    case R.id.chbAddDel:
    case R.id.chbVisible:
      invalidateOptionsMenu();
      break;
    case R.id.btnFrag:
      frag = (frag == frag1) ? frag2 : frag1;
      getFragmentManager().beginTransaction().replace(R.id.cont, frag)
          .commit();
      break;
    default:
      break;
    }

  }
}

В onCreateOptionsMenu настраиваем видимость группы groupVsbl в зависимости от значения чекбокса chbVisible.

В зависимости от значения чекбокса chbAddDel создаем или удаляем элемент.

В onСlick для чекбоксов вызываем метод invalidateOptionsMenu - перерисовка меню/ActionBar. А по нажатию на кнопку поочередно выводим на экран Fragment1 или Fragment2.

 

Все сохраняем и запускаем приложение.

 

Жмем галку Добавить/удалить. Появляется элемент. Мы добавили MenuItem в Menu.

 

Жмем галку Показать/скрыть. Появляется элемент. Мы показали группу меню, в которой один пункт.

Соответственно, убирая галки - убираете элементы.

 

Понажимаем кнопку Фрагмент. Появляется элемент то одного, то другого фрагмента.

 

 

Еще, как вариант, можно играться с видимостью не всей группы, а конкретного элемента - метод setVisible.

Если в ActionBar нажать на overflow-кнопку, будет вызван метод onPrepareOptionsMenu для Activity и для фрагмента, который сейчас отображен. 

 

На следующем уроке:

- работаем с ActionMode


Присоединяйтесь к нам в Telegram:

- в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.

- в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Compose, Kotlin, RxJava, Dagger, Тестирование, Performance 

- ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня




Language

Автор сайта

Дмитрий Виноградов

Подробнее можно посмотреть или почитать.

Никакие другие люди не имеют к этому сайту никакого отношения и просто занимаются плагиатом.

Социальные сети

 

В канале я публикую ссылки на интересные и полезные статьи по Android

В чате можно обсудить вопросы и проблемы, возникающие при разработке



Группа ВКонтакте



Поддержка проекта

Яндекс
410011180491924

WebMoney
R248743991365
Z551306702056

Paypal