Рассмотрим новый компонент библиотеки поддержки материального дизайна BottomNavigationView. Это нижняя панель навигации, позволяющая переключаться между экранами приложения в одно касание, она предназначена в основном для смартфонов, поскольку расположение в нижней части экрана обеспечивает удобный и быстрый доступ для пользователя.
Этот компонент доступен в Design Support Library с версии 25.0.0 и Google рекомендует его к применению с соблюдением таких принципов дизайна:
- Рекомендуется только для смартфонов, на планшетах и других устройствах с большим экраном лучше использовать боковое меню навигации.
- Ширина областей значков зависит от их количества и может варьироваться от 80 до 168 dp. Высота панели — 56 dp, размер иконки 24×24 dp.
- Панель должна содержать не меньше 3-х, но не больше 5-ти кнопок, кнопки должны помещаться на экране и не скроллиться.
- Переключение между экранами только по тапу на кнопке, свайп не используется, что дает возможность комбинировать BottomNavigationView с вкладками. Но Google рекомендует подходить к такой комбинации с осторожностью, чтобы не дезориентировать пользователя.
- Можно закрашивать активный значок в основной цвет приложения, либо использовать белый или черный цвета, если нижняя панель навигации цветная. Не разукрашивайте значки в разные цвета.
- Текстовые метки должны быть максимально короткими и информативными, избегайте длинных надписей.
- Нажатие значка на нижней панели навигации должно привести пользователя прямо к связанному со значком окну, или обновить текущее окно. Значки не должны открывать меню или всплывающие окна. Кнопка «Назад» на устройстве не должна позволять перемещаться между экранами нижней панели навигации.
- Нижняя панель навигации может исчезать с экрана при прокрутке вверх и появляться при возвращении.
Ссылка на более подробную спецификацию есть в описании видео, а мы с вами переходим к практике — я покажу, как внедрить BottomNavigationView в приложение.
Для добавления поддержки нижней панели навигации в файл сборки уровня модуля нужно добавить такие зависимости:
compile 'com.android.support:appcompat-v7:25.0.0' compile 'com.android.support:design:25.0.0'
В файле макета главного экрана такая разметка:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:src="@drawable/ic_map_24dp" android:id="@+id/img_map" android:layout_width="240dp" android:layout_height="240dp" android:layout_centerInParent="true" /> <ImageView android:src="@drawable/ic_apps_24dp" android:id="@+id/img_dial" android:layout_width="240dp" android:layout_height="240dp" android:layout_centerInParent="true" android:visibility="gone" /> <ImageView android:src="@drawable/ic_email_24dp" android:id="@+id/img_mail" android:layout_width="240dp" android:layout_height="240dp" android:layout_centerInParent="true" android:visibility="gone" /> <android.support.design.widget.BottomNavigationView android:id="@+id/bottom_navigation" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" app:itemBackground="@color/colorPrimary" app:itemIconTint="@color/bottom_navigation_item_background_colors" app:itemTextColor="@color/bottom_navigation_item_background_colors" app:menu="@menu/menu_bottom_navigation" /> </RelativeLayout>
Здесь три расположенных по центру Imageview, два из которых скрыты изначально при помощи атрибута visibility со значением gone. Мы будем просто отображать по очереди изображения в них в зависимости от выбранного значка в BottomNavigationView.
А ниже — виджет BottomNavigationView, он имеет такие атрибуты:
- itemBackground : цвет фона элемента панели. Может быть установлен из кода методом setItemBackgroundResource()
- itemIconTint : цвет иконки элемента панели. Может быть установлен из кода методом setItemIconTintList()
- itemTextColor : цвет текста элементов панели. Может быть установлен из кода методом setItemTextColor()
Эти два атрибута ссылаются на файл ресурса, который устанавливает цвет в зависимости от того, активен элемент или нет.
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:color="@android:color/darker_gray" android:state_checked="false"/> <item android:color="@android:color/white" android:state_checked="true"/> </selector>
Последний атрибут BottomNavigationView app:menu ссылается на предварительно созданный файл ресурса menu_bottom_navigation.xml, который содержит пункты нижней панели навигации. Они практически не отличаются от обычного меню:
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/action_map" android:icon="@android:drawable/ic_dialog_map" android:title="@string/map"/> <item android:id="@+id/action_dial" android:icon="@android:drawable/ic_dialog_dialer" android:title="@string/dial" /> <item android:id="@+id/action_mail" android:icon="@android:drawable/ic_dialog_email" android:title="@string/mail" /> </menu>
Теперь код главного класса MainActivity.java:
package ... import android.os.Bundle; import android.support.annotation.NonNull; import android.support.design.widget.BottomNavigationView; import android.support.v7.app.AppCompatActivity; import android.view.MenuItem; import android.view.View; import android.widget.ImageView; public class MainActivity extends AppCompatActivity { ImageView imgMap; ImageView imgDial; ImageView imgMail; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); imgMap = (ImageView) findViewById(R.id.img_map); imgDial = (ImageView) findViewById(R.id.img_dial); imgMail = (ImageView) findViewById(R.id.img_mail); BottomNavigationView bottomNavigationView = (BottomNavigationView) findViewById(R.id.bottom_navigation); bottomNavigationView.setOnNavigationItemSelectedListener( new BottomNavigationView.OnNavigationItemSelectedListener() { @Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { switch (item.getItemId()) { case R.id.action_map: imgMap.setVisibility(View.VISIBLE); imgDial.setVisibility(View.GONE); imgMail.setVisibility(View.GONE); break; case R.id.action_dial: imgMap.setVisibility(View.GONE); imgDial.setVisibility(View.VISIBLE); imgMail.setVisibility(View.GONE); break; case R.id.action_mail: imgMap.setVisibility(View.GONE); imgDial.setVisibility(View.GONE); imgMail.setVisibility(View.VISIBLE); break; } return false; } }); } }
Здесь мы объявляем и находим все экранные компоненты. BottomNavigationView присваиваем слушатель, который определяет нажатие на пункты панели по идентификаторам и прописываем нужные действия в конструкции switch.
В нашем случае для простоты примера просто меняется видимость картинок в ImageView на главном экране. Но можно, например, реализовать открытие фрагментов с различным контентом и т.п.
Вот так приложение выглядит на устройстве:
При нажатии значки панели анимируются и меняют цвет. А если удалить атрибуты цвета иконки и текста значка в файле разметки, то фон панели станет по умолчанию белым , активный значок окрасится в основной цвет приложения, а неактивные значки станут серыми.
В качестве домашнего задания попробуйте добавить один или два пункта в нижнюю панель навигации, и посмотрите, как поведут себя значки. Не добавляйте больше пяти пунктов — получите ошибку.