Урок 108. Android 3. ActionBar. Навигация - табы и выпадающий список


 В этом уроке:

- используем навигацию в ActionBar


На прошлом уроке мы рассмотрели добавление элементов ActionBar. Пользователю эти элементы удобно использовать для совершения каких-либо операций в приложении. Например, в почтовой программе это может быть удаление письма, пересылка, ответ и т.д.

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


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

Project name: P1081_ActionBarNavigation
Build Target: Android 4.1
Application name: ActionBarItems
Package name: ru.startandroid.develop.p1081actionbarnavigation
Create Activity: MainActivity


Никакие строки не добавляем, основной layout не трогаем.


Табы

Кодим MainActivity.java:

package ru.startandroid.develop.p1081actionbarnavigation;

import android.app.ActionBar;
import android.app.ActionBar.Tab;
import android.app.Activity;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.util.Log;

public class MainActivity extends Activity implements ActionBar.TabListener {

 
final String LOG_TAG = "myLogs";

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

    ActionBar bar = getActionBar
();

    bar.setNavigationMode
(ActionBar.NAVIGATION_MODE_TABS);

    Tab tab = bar.newTab
();
    tab.setText
("tab1");
    tab.setTabListener
(this);
    bar.addTab
(tab);

    tab = bar.newTab
();
    tab.setText
("tab2");
    tab.setTabListener
(this);
    bar.addTab
(tab);

 
}

 
@Override
 
public void onTabReselected(Tab tab, FragmentTransaction ft) {
   
Log.d(LOG_TAG, "reselected tab: " + tab.getText());
 
}

 
@Override
 
public void onTabSelected(Tab tab, FragmentTransaction ft) {
   
Log.d(LOG_TAG, "selected tab: " + tab.getText());
 
}

 
@Override
 
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
   
Log.d(LOG_TAG, "unselected tab: " + tab.getText());
 
}
}

Смотрим, что нам нужно, чтобы включить табы.

В onCreate мы получаем доступ к ActionBar и устанавливаем для него режим навигации в NAVIGATION_MODE_TABS. Далее идет добавление табов. Тут все несложно – создаем, пишем текст, присваиваем обработчика, добавляем в ActionBar.

Обработчиком для табов мы сделали MainActivity, оно реализует методы интерфейса ActionBar.TabListener:

onTabReselected – выбран уже выбранный таб

onTabSelected – таб выбран

onTabUnselected – таб более не выбран

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


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

Видим табы

Сейчас выбран первый таб и лог сразу об этом сообщает:

selected tab: tab1


Нажмем на второй таб,

смотрим логи:

unselected tab: tab1
selected tab: tab2

Первый таб «развыбран», а второй выбран.


Еще раз нажмем на второй таб:

reselected tab: tab2

Второй таб перевыбран. Все логично и понятно.


Я, чтобы не перегружать урок, не стал реализовывать какие-либо операции по навигации в приложении. А, вообще, подразумевается, что в методах обработчика мы кодим операции с фрагментами. Нам даже любезно предоставляют объект FragmentTransaction для этих целей. При этом хелп предупреждает, что в этих методах нам не надо самим вызывать метод commit, а также мы не можем добавлять транзакцию в BackStack.


Выпадающий список

Теперь посмотрим, как работает навигация с выпадающим списком.

Перепишем MainActivity.java:

package ru.startandroid.develop.p1081actionbarnavigation;

import android.app.ActionBar;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.widget.ArrayAdapter;

public class MainActivity extends Activity implements
   
ActionBar.OnNavigationListener {

 
String[] data = new String[] { "one", "two", "three" };

 
final String LOG_TAG = "myLogs";

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

    ActionBar bar = getActionBar
();
    bar.setNavigationMode
(ActionBar.NAVIGATION_MODE_LIST);

    ArrayAdapter<String> adapter =
new ArrayAdapter<String>(this,
        android.R.layout.simple_spinner_item, data
);
    adapter.setDropDownViewResource
(android.R.layout.simple_spinner_dropdown_item);
    bar.setListNavigationCallbacks
(adapter, this);
 
}

 
@Override
 
public boolean onNavigationItemSelected(int itemPosition, long itemId) {
   
Log.d(LOG_TAG, "selected: position = " + itemPosition + ", id = "
       
+ itemId + ", " + data[itemPosition]);
   
return false;
 
}
}

В onCreate получаем ActionBar и включаем ему режим навигации NAVIGATION_MODE_LIST. Для выпадающего списка необходимо создать адаптер, реализующий SpinnerAdapter. Пусть это будет ArrayAdapter. При создании используем массив из трех строк. Далее вызываем метод setListNavigationCallbacks, в который передаем адаптер и обработчик.

Обработчиком у нас снова является Activity, реализует метод onNavigationItemSelected интерфейса ActionBar.OnNavigationListener. Этот метод дает нам позицию и id выбранного из списка элемента. Выводим в лог эту инфу и соответствующий элемент массива.

В манифесте я прописал для MainActivity атрибут темы: android:theme="@android:style/Theme.Holo.Light". Иначе был темный текст на темном фоне.


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

Первый элемент сразу выбран. В логах видим:

selected: position = 0, id = 0, one


Выберем какой-нить другой элемент из списка

В логах:

selected: position = 2, id = 2, three

Снова все логично и понятно.


Для обоих видов навигации мы всегда можем получить текущий выбранный элемент с помощью метода getSelectedNavigationIndex. А для навигации с табами есть также метод getSelectedTab, возвращающий текущий выбранный таб.

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


При этом, если места будет недостаточно, то ActionBar разделит все свои элементы на две полосы.

Начиная с четвертой версии Андроид, можно использовать атрибут uiOptions для Activity или Application в манифесте. Если присвоить ему значение splitActionBarWhenNarrow, то результат при нехватке места получится такой:

Элементы ушли вниз. Правда, при этом почему-то перестает работать withText в showAsAction.


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

- работаем с ListFragment