2.3 Настройка BottomNavigationView

Теперь настроим BottomNavigationView в макете и в классе MainActivity.

Откроем макет activity_main.xml и отредактируем BottomNavigationView. Для начала добавим ресурс меню (нажмите правой кнопкой на папку res и выберите New -> Android Resource File, после чего создайте ресурс меню.

Откройте меню bottom_menu.xml. Меню представляет собой xml-файл с корневым элементом menu. Каждый пункт меню представляет собой элемент item с различными параметрами. Мы создадим три пункта, укажем иконки для каждого пункта (они были предварительно добавлены в папку drawable, а также каждому пункту меню была присвоена текстовая надпись и id.

bottom_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/wintersun"
        android:icon="@drawable/ic_baseline_looks_one_24"
        android:title="Wintersun"/>
    <item
        android:id="@+id/insomnium"
        android:icon="@drawable/ic_baseline_looks_two_24"
        android:title="Insomnium"/>
    <item
        android:id="@+id/belakor"
        android:icon="@drawable/ic_baseline_looks_3_24"
        android:title="Be'lakor"/>
</menu>

Вернемся в макет activity_main.xml и добавим меню в BottomNavigationView.

activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    ...

    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bottom_navigation"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        android:layout_marginBottom="42dp"
        android:background="@android:color/transparent"
        app:labelVisibilityMode="labeled"
        app:menu="@menu/bottom_menu" /> <!-- Добавили меню -->

</FrameLayout>

Обратите внимание на атрибут app:labelVisibilityMode="labeled". Он определяет режим отображения пунктов BottomNavigationView. В этом режиме всегда видны все надписи и иконки для каждого BottomNavigationView. Попробуйте поменять значение атрибута и посмотреть, как будет вести себя BottomNavigationView в том или ином случае.

Следующим шагом мы хотим поменять шрифт для надписей BottomNavigationView. Для этого откроем ресурс themes.xml и добавим туда новый стиль. Предварительно добавим нужный шрифт в проект.

themes.xml
<resources xmlns:tools="http://schemas.android.com/tools">
    <style name="Theme.Fragments" parent="Theme.MaterialComponents.DayNight.NoActionBar">
        <item name="colorPrimary">@color/purple_500</item>
        <item name="colorPrimaryVariant">@color/purple_700</item>
        <item name="colorOnPrimary">@color/white</item>
        <item name="colorSecondary">@color/teal_200</item>
        <item name="colorSecondaryVariant">@color/teal_700</item>
        <item name="colorOnSecondary">@color/black</item>
    </style>

    <style name="Widget.BottomNavigationView" parent="Widget.Design.BottomNavigationView">
        <item name="fontFamily">@font/marker</item>
    </style>
</resources>

Вернемся в activity_main.xml и изменим описание BottomNavigationView.

activity_main.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    ...

    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bottom_navigation"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        android:layout_marginBottom="42dp"
        android:background="@android:color/transparent"

        android:theme="@style/Widget.BottomNavigationView"
        
        app:labelVisibilityMode="labeled"
        app:menu="@menu/bottom_menu" />

</FrameLayout>

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

bottom_colors.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:color="#ff0000"
        android:state_checked="false"/>
    <item
        android:color="#fff000"
        android:state_checked="true"/>
</selector>

Элемент selector позволяет выбрать один из представленных item по тому или иному условию. В качестве условия выступает атрибут state_checked. То есть, если пункт меню будет иметь состояние checked="true", то будет выбран цвет #fff000 (желтый). Если пункт меню будет находиться в состоянии checked="false", то будет выбран красный цвет.

Далее вернемся в activity_main.xml и укажем в качестве цвета для иконок и текста ресурс bottom_colors.xml.

activity_main.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    ...

    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bottom_navigation"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        android:layout_marginBottom="42dp"
        android:background="@android:color/transparent"
        android:theme="@style/Widget.BottomNavigationView"
        
        app:itemIconTint="@color/bottom_colors"
        app:itemTextColor="@color/bottom_colors"
        
        app:labelVisibilityMode="labeled"
        app:menu="@menu/bottom_menu" />
</FrameLayout>

Проверим работу приложения. Обратите внимание, что листание фрагментов и нажатие на пункты меню никак не синхронизированы - листание не приводит к изменению активного пункта меню, а нажатие на пункт меню не пролистывает фрагмент. Вернемся в класс MainActivity и попробуем синхронизировать эти виджеты.

Last updated