Статьи

Как кодировать навигационный ящик для приложения Android

Конечный продукт
Что вы будете создавать

Команда разработчиков материалов в Google определяет функциональность панели навигации в Android следующим образом:

Панель навигации скользит слева и содержит пункты назначения навигации для вашего приложения.

Примером популярного приложения для Android, в котором реализован блок навигации, является приложение «Входящие» от Google, которое использует блок навигации для перехода к различным разделам приложения. Вы можете проверить это самостоятельно, загрузив приложение «Входящие» из магазина Google Play, если оно еще не установлено на вашем устройстве. На приведенном ниже снимке экрана показана папка «Входящие» с открытым ящиком навигации.

Приложение Google Inbox для Android

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

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

В этом посте вы узнаете, как отображать элементы навигации внутри панели навигации в Android. Мы расскажем, как использовать DrawerLayout и NavigationView API для выполнения этой задачи. В качестве бонуса вы также узнаете, как использовать функцию шаблонов Android Studio для быстрой загрузки проекта с помощью панели навигации.

Пример проекта (на Kotlin) для этого учебного руководства можно найти в нашем репозитории GitHub, чтобы вы могли легко следить за ним.

Чтобы следовать этому руководству, вам понадобится:

Запустите Android Studio и создайте новый проект (вы можете назвать его NavigationDrawerDemo ) с пустым действием MainActivity . Не забудьте также установить флажок Включить поддержку Kotlin .

Android Studio новый проект диалоговое окно

Чтобы начать использовать DrawerLayout и NavigationView в своем проекте, вам необходимо импортировать поддержку дизайна, а также артефакт поддержки Android. Поэтому добавьте их в файл build.gradle вашего модуля, чтобы импортировать их.

1
2
3
4
dependencies {
    implementation ‘com.android.support:design:27.0.2’
    implementation ‘com.android.support:support-v4:27.0.2’
}

Кроме того, DrawerLayout виджет DrawerLayout виджет NavigationView в ваш файл res / layout / activlty_main.xml .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?xml version=»1.0″ encoding=»utf-8″?>
<android.support.v4.widget.DrawerLayout
        xmlns:android=»https://schemas.android.com/apk/res/android»
        xmlns:app=»http://schemas.android.com/apk/res-auto»
        xmlns:tools=»http://schemas.android.com/tools»
        android:id=»@+id/drawer_layout»
        android:layout_width=»match_parent»
        android:layout_height=»match_parent»
        tools:openDrawer=»start»>
 
    <include
            layout=»@layout/app_bar_main»
            android:layout_width=»match_parent»
            android:layout_height=»match_parent» />
 
    <android.support.design.widget.NavigationView
            android:id=»@+id/nav_view»
            android:layout_width=»wrap_content»
            android:layout_height=»match_parent»
            android:layout_gravity=»start»
            app:headerLayout=»@layout/nav_header_main»
            app:menu=»@menu/activity_main_drawer» />
 
</android.support.v4.widget.DrawerLayout>

Здесь мы создали виджет DrawerLayout с идентификатором drawer_layout . Свойство tools:openDrawer используется для отображения панели навигации, когда макет XML открыт в представлении дизайна Android Studio.

Официальная документация гласит следующее о DrawerLayout :

DrawerLayout действует как контейнер верхнего уровня для содержимого окна, что позволяет DrawerLayout интерактивные виды «ящиков» из одного или обоих вертикальных краев окна.

После добавления виджета DrawerLayout мы включили дочерний макет, который указывает на @layout/app_bar_main .

Вот мой файл ресурсов app_bar_main.xml . Этот файл просто содержит CoordinatorLayout , AppBarLayout и виджет Toolbar .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?xml version=»1.0″ encoding=»utf-8″?>
<android.support.design.widget.CoordinatorLayout
        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»>
 
    <android.support.design.widget.AppBarLayout
            android:layout_width=»match_parent»
            android:layout_height=»wrap_content»
            android:fitsSystemWindows=»true»
            android:theme=»@style/AppTheme.AppBarOverlay»>
 
        <android.support.v7.widget.Toolbar
                android:id=»@+id/toolbar_main»
                android:layout_width=»match_parent»
                android:layout_height=»?attr/actionBarSize»
                android:background=»?attr/colorPrimary»
                app:layout_scrollFlags=»scroll|enterAlways»
                app:popupTheme=»@style/AppTheme.PopupOverlay» />
 
    </android.support.design.widget.AppBarLayout>
</android.support.design.widget.CoordinatorLayout>

Наконец, мы создали виджет NavigationView . Официальная документация гласит следующее о NavigationView :

NavigationView представляет собой стандартное меню навигации для приложения. Содержимое меню может быть заполнено файлом ресурсов меню.

В виджете XML NavigationView вы можете видеть, что мы добавили атрибут android:layout_gravity со значением start . Это используется для позиционирования выдвижного ящика — вы хотите, чтобы выдвижной ящик выдвигался слева или справа (начало или конец в версиях платформы, которые поддерживают направление компоновки). В нашем собственном случае ящик выйдет слева.

Мы также включили атрибут app:headerLayout который указывает на @layout/nav_header_main . Это добавит View в качестве заголовка меню навигации.

Вот мой файл ресурсов макета nav_header_main.xml :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?xml version=»1.0″ encoding=»utf-8″?>
<LinearLayout xmlns:android=»http://schemas.android.com/apk/res/android»
              android:id=»@+id/nav_header»
              android:layout_width=»match_parent»
              android:layout_height=»160dp»
              android:background=»@color/colorAccent»
              android:clickable=»true»
              android:focusable=»true»
              android:foreground=»?attr/selectableItemBackgroundBorderless»
              android:gravity=»bottom»
              android:orientation=»vertical»
              android:padding=»16dp»
              android:theme=»@style/ThemeOverlay.AppCompat.Dark»>
 
    <ImageView
            android:id=»@+id/nav_header_imageView»
            android:layout_width=»64dp»
            android:layout_height=»64dp»
            android:src=»@mipmap/ic_launcher» />
 
    <TextView
            android:id=»@+id/nav_header_textView»
            android:layout_width=»match_parent»
            android:layout_height=»wrap_content»
            android:paddingTop=»16dp»
            android:text=»Chike Mgbemena»
            android:textAppearance=»@style/TextAppearance.AppCompat.Body1″ />
</LinearLayout>

Этот файл макета просто имеет LinearLayout , ImageView и TextView .

Предварительный просмотр макета Android Studio

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

1
2
<android.support.design.widget.NavigationView
       app:menu=»@menu/activity_main_drawer» />

Вот файл ресурсов меню res / menu / activity_main_drawer.xml :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<?xml version=»1.0″ encoding=»utf-8″?>
<menu xmlns:android=»http://schemas.android.com/apk/res/android»>
    <group>
        <item android:id=»@+id/nav_item_one»
              android:icon=»@drawable/ic_drafts_black_24dp»
              android:title=»Item 1″ />
        <item android:id=»@+id/nav_item_two»
              android:icon=»@drawable/ic_drafts_black_24dp»
              android:title=»Item 2″ />
        <item android:id=»@+id/nav_item_three»
              android:icon=»@drawable/ic_drafts_black_24dp»
              android:title=»Item 3″ />
    </group>
 
    <group android:id=»@+id/group_menu»>
        <item android:id=»@+id/nav_item_four»
              android:title=»Item 4″ />
        <item android:id=»@+id/nav_item_five»
              android:title=»Item 5″ />
    </group>
 
    <item android:title=»Title 1″>
        <menu>
            <item android:id=»@+id/nav_item_six»
                  android:icon=»@drawable/ic_drafts_black_24dp»
                  android:title=»Item 6″ />
            <item android:id=»@+id/nav_item_seven»
                  android:icon=»@drawable/ic_drafts_black_24dp»
                  android:title=»Item 7″ />
        </menu>
    </item>
</menu>

Здесь мы определили Menu используя <menu> который служит контейнером для пунктов меню. <item> создает MenuItem , который представляет отдельный элемент в меню.

Затем мы определили нашу первую группу меню, используя <group> . <group> служит невидимым контейнером для <item> — в нашем случае пунктов меню. Каждый из <item> имеет идентификатор, значок и заголовок. Обратите внимание, что для нас будет отображаться горизонтальная линия в конце каждой <group> , когда она отображается в окне навигации.

<item> также может содержать вложенный элемент <menu> для создания подменю — мы сделали это в нашем последнем <item> . Обратите внимание, что этот последний <item> имеет свойство title.

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

Далее мы собираемся инициализировать экземпляры наших DrawerLayout и ActionBarDrawerToggle . Инициализация будет происходить внутри onCreate() в MainActivity.kt .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import android.content.res.Configuration
import android.os.Bundle
import android.support.v4.widget.DrawerLayout
import android.support.v7.app.ActionBarDrawerToggle
import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.Toolbar
import android.view.MenuItem
 
class MainActivity : AppCompatActivity() {
 
    private lateinit var drawer: DrawerLayout
    private lateinit var toggle: ActionBarDrawerToggle
 
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
 
        val toolbar: Toolbar = findViewById(R.id.toolbar_main)
        setSupportActionBar(toolbar)
 
        drawer = findViewById(R.id.drawer_layout)
 
        toggle = ActionBarDrawerToggle(this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close)
        drawer.addDrawerListener(toggle)
        supportActionBar?.setDisplayHomeAsUpEnabled(true)
        supportActionBar?.setHomeButtonEnabled(true)
    }
 
    // …
}

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

  • родительский контекст — например, в Activity вы используете, в то время как во Fragment вы вызываете getActivity()
  • экземпляр виджета DrawerLayout для ссылки на ActionBar
  • значок для размещения в верхней части значка приложения, чтобы указать, что есть переключатель
  • строковые ресурсы для операций открытия и закрытия соответственно (для доступности)

Мы addDrawerListener() метод addDrawerListener() для DrawerLayout чтобы связать ActionBarDrawerToggle с DrawerLayout .

Обратите внимание, что мы также активируем значок приложения с помощью setHomeButtonEnabled() и setHomeButtonEnabled() его для навигации «вверх» с помощью setDisplayHomeAsUpEnabled() .

Затем мы пересылаем методы обратного вызова действий onPostCreate() , onConfigurationChanged() и onOptionsItemSelected() в переключатель:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
class MainActivity : AppCompatActivity() {
 
    // …
 
    override fun onPostCreate(savedInstanceState: Bundle?) {
        super.onPostCreate(savedInstanceState)
        toggle.syncState()
    }
 
    override fun onConfigurationChanged(newConfig: Configuration?) {
        super.onConfigurationChanged(newConfig)
        toggle.onConfigurationChanged(newConfig)
    }
 
    override fun onOptionsItemSelected(item: MenuItem?): Boolean {
        if (toggle.onOptionsItemSelected(item)) {
            return true
        }
        return super.onOptionsItemSelected(item)
    }
}

Вот что syncState() соответствии с официальной документацией :

Синхронизирует состояние индикатора / доступности ящика со связанным DrawerLayout … Это следует вызывать из метода onPostCreate вашего Activity для синхронизации после восстановления состояния экземпляра DrawerLayout, а также в любое другое время, когда состояние могло расходиться таким образом. способ, которым ActionBarDrawerToggle не был уведомлен. (Например, если вы перестанете пересылать соответствующие события ящика на определенный период времени.)

На данный момент, мы можем запустить приложение!

Первое приложение демо

Как вы можете видеть, при запуске приложения на панели действий появится значок панели навигации «гамбургер». Попробуйте нажать значок этого приложения, чтобы открыть ящик. Кроме того, нажатие на элементы панели навигации ничего не изменит — мы рассмотрим эту часть в следующем разделе.

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

Во-первых, ваша деятельность должна реализовывать NavigationView.OnNavigationItemSelectedListener .

1
2
3
class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener {
    // …
}

onNavigationItemSelected() этот контракт или интерфейс, мы теперь должны переопределить единственный метод: onNavigationItemSelected() .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener {
     
    // …
 
    override fun onNavigationItemSelected(item: MenuItem): Boolean {
 
        when (item.itemId) {
            R.id.nav_item_one -> Toast.makeText(this, «Clicked item one», Toast.LENGTH_SHORT).show()
            R.id.nav_item_two -> Toast.makeText(this, «Clicked item two», Toast.LENGTH_SHORT).show()
            R.id.nav_item_three -> Toast.makeText(this, «Clicked item three», Toast.LENGTH_SHORT).show()
            R.id.nav_item_four -> Toast.makeText(this, «Clicked item four», Toast.LENGTH_SHORT).show()
        }
        return true
    }
}

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

Затем мы должны инициализировать наш NavigationView и установить этот слушатель внутри onCreate() нашей деятельности.

1
2
3
4
5
6
7
8
9
class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener {
    // …
    override fun onCreate(savedInstanceState: Bundle?) {
        // …
        val navigationView: NavigationView = findViewById(R.id.nav_view)
        navigationView.setNavigationItemSelectedListener(this)
        // …
    }
// …

Запустите проект снова!

Демонстрация приложения с настройкой щелчков элементов навигации

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

Вы заметите, что когда вы нажимаете на элемент, ящик остается. Было бы лучше, если бы он автоматически закрывался при каждом нажатии на элемент. Посмотрим, как это сделать.

01
02
03
04
05
06
07
08
09
10
11
override fun onNavigationItemSelected(item: MenuItem): Boolean {
 
    when (item.itemId) {
        R.id.nav_item_one -> Toast.makeText(this, «Clicked item one», Toast.LENGTH_SHORT).show()
        R.id.nav_item_two -> Toast.makeText(this, «Clicked item two», Toast.LENGTH_SHORT).show()
        R.id.nav_item_three -> Toast.makeText(this, «Clicked item three», Toast.LENGTH_SHORT).show()
        R.id.nav_item_four -> Toast.makeText(this, «Clicked item four», Toast.LENGTH_SHORT).show()
    }
    drawer.closeDrawer(GravityCompat.START)
    return true
}

Чтобы закрыть ящик после щелчка ссылки, просто вызовите closeDrawer() для экземпляра DrawerLayout и передайте GravityCompat.START методу.

Запустите проект еще раз и посмотрите результат!

Когда ящик открыт, пользователю будет удобнее не закрывать домашнюю активность, если нажата кнопка « Назад» . Так работают популярные приложения, такие как Google Inbox.

Таким образом, когда ящик открыт и нажата кнопка « Назад» , закрывайте только ящик вместо текущего домашнего действия. Затем, если пользователь снова нажимает кнопку « Назад» , домашняя активность должна быть закрыта.

Вот как мы можем достичь этого:

1
2
3
4
5
6
7
override fun onBackPressed() {
    if (drawer.isDrawerOpen(GravityCompat.START)) {
        drawer.closeDrawer(GravityCompat.START)
    } else {
        super.onBackPressed()
    }
}

Запустите проект еще раз и проверьте его!

Теперь, когда вы узнали об API, которые используются для создания навигационной панели, я покажу вам ярлык, который сделает его быстрее в следующий раз. Вы можете просто использовать шаблон вместо того, чтобы кодировать панель навигации Activity с нуля.

Android Studio предоставляет шаблоны кода, которые соответствуют рекомендациям по проектированию и разработке Android. Эти существующие шаблоны кода (доступные на Java и Kotlin) могут помочь вам быстро запустить ваш проект. Один из таких шаблонов может быть использован для создания деятельности в области навигации.

Я покажу вам, как использовать эту удобную функцию в Android Studio.

Для нового проекта запустите Android Studio.

Диалог создания проекта Android

Введите имя приложения и нажмите кнопку « Далее» .

Вы можете оставить настройки по умолчанию такими, как они есть в диалоговом окне « Целевые устройства Android ». Нажмите кнопку Далее еще раз.

Диалог добавления активности на мобильный

В диалоговом окне « Добавить действие на мобильное устройство » прокрутите вниз и выберите « Активность в окне навигации». Нажмите кнопку Далее после этого.

Диалоговое окно «Настроить активность»

В последнем диалоговом окне вы можете переименовать имя действия, имя макета или заголовок, если хотите. Наконец, нажмите кнопку Готово , чтобы принять все конфигурации.

Android Studio теперь помогла нам создать проект с активностью навигационной панели. Очень круто!

Вам настоятельно рекомендуется изучить сгенерированный код.

Вы также можете использовать шаблоны для уже существующего проекта Android Studio. Просто зайдите в Файл> Создать> Активность> Активность в Навигационной панели .

Навигация из меню файлов тоже

Шаблоны, которые входят в состав Android Studio, хороши для простых макетов и создания базовых приложений, но если вы хотите запустить свое приложение еще дальше, вы можете рассмотреть некоторые из шаблонов приложений, доступных на Envato Market .

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

Из этого руководства вы узнали, как создать блок навигации в Android с помощью API DrawerLayout и NavigationView с нуля. Мы также изучили, как легко и быстро использовать шаблоны Android Studio для создания навигационной панели.

Я настоятельно рекомендую ознакомиться с официальными рекомендациями по дизайну материалов для навигационных ящиков, чтобы узнать больше о том, как правильно проектировать и использовать навигационные ящики в Android.

Чтобы узнать больше о кодировании для Android, ознакомьтесь с другими нашими курсами и учебными пособиями здесь, на Envato Tuts +!

  • Android SDK
    Создание музыкального приложения с помощью шаблона приложения для Android
  • Android SDK
    Упростите разработку приложений для Android с Anko
    Ашраф Хатхибелагал
  • Android SDK
    Создание интерфейса с вкладками «Дизайн материала» в приложении для Android
  • Шаблоны приложений
    20 лучших шаблонов для Android-приложений 2019 года
    Нона Блэкман
  • Android SDK
    Кодирование Android-галереи изображений с помощью Glide