Команда разработчиков материалов в Google определяет функциональность панели навигации в Android следующим образом:
Панель навигации скользит слева и содержит пункты назначения навигации для вашего приложения.
Примером популярного приложения для Android, в котором реализован блок навигации, является приложение «Входящие» от Google, которое использует блок навигации для перехода к различным разделам приложения. Вы можете проверить это самостоятельно, загрузив приложение «Входящие» из магазина Google Play, если оно еще не установлено на вашем устройстве. На приведенном ниже снимке экрана показана папка «Входящие» с открытым ящиком навигации.
Пользователь может просматривать навигационную панель, проводя пальцем по левому краю действия. Они также могут найти его в домашней активности (верхний уровень приложения), нажав значок приложения (также известный как меню «гамбургер») на панели действий.
Обратите внимание, что если в вашем приложении много разных пунктов назначения (например, более шести), рекомендуется использовать навигационный ящик.
В этом посте вы узнаете, как отображать элементы навигации внутри панели навигации в Android. Мы расскажем, как использовать DrawerLayout
и NavigationView
API для выполнения этой задачи. В качестве бонуса вы также узнаете, как использовать функцию шаблонов Android Studio для быстрой загрузки проекта с помощью панели навигации.
Пример проекта (на Kotlin) для этого учебного руководства можно найти в нашем репозитории GitHub, чтобы вы могли легко следить за ним.
Предпосылки
Чтобы следовать этому руководству, вам понадобится:
- Android Studio 3.0 или выше
- Плагин Kotlin 1.1.51 или выше
1. Создайте проект Android Studio
Запустите Android Studio и создайте новый проект (вы можете назвать его NavigationDrawerDemo
) с пустым действием MainActivity
. Не забудьте также установить флажок Включить поддержку Kotlin .
2. Добавление DrawerLayout и NavigationView
Чтобы начать использовать 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
.
Чтобы включить пункты меню для панели навигации, мы можем использовать атрибут 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
, вам пришлось бы поддерживать список, а также стилизовать его, чтобы он соответствовал рекомендованным спецификациям материала для навигационного блока .
3. Инициализация компонентов
Далее мы собираемся инициализировать экземпляры наших 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 не был уведомлен. (Например, если вы перестанете пересылать соответствующие события ящика на определенный период времени.)
4. Тестирование приложения
На данный момент, мы можем запустить приложение!
Как вы можете видеть, при запуске приложения на панели действий появится значок панели навигации «гамбургер». Попробуйте нажать значок этого приложения, чтобы открыть ящик. Кроме того, нажатие на элементы панели навигации ничего не изменит — мы рассмотрим эту часть в следующем разделе.
5. Обработка событий клика
Теперь давайте посмотрим, как обрабатывать события щелчка для каждого элемента в навигационной панели. Обратите внимание, что нажатие на любой элемент должно привести вас к новому действию или фрагменту — вот почему он называется навигационным блоком!
Во-первых, ваша деятельность должна реализовывать 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
методу.
Запустите проект еще раз и посмотрите результат!
6. Обработка нажатой кнопки «Назад»
Когда ящик открыт, пользователю будет удобнее не закрывать домашнюю активность, если нажата кнопка « Назад» . Так работают популярные приложения, такие как Google Inbox.
Таким образом, когда ящик открыт и нажата кнопка « Назад» , закрывайте только ящик вместо текущего домашнего действия. Затем, если пользователь снова нажимает кнопку « Назад» , домашняя активность должна быть закрыта.
Вот как мы можем достичь этого:
1
2
3
4
5
6
7
|
override fun onBackPressed() {
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START)
} else {
super.onBackPressed()
}
}
|
Запустите проект еще раз и проверьте его!
7. Бонус: использование шаблонов Android Studio
Теперь, когда вы узнали об API, которые используются для создания навигационной панели, я покажу вам ярлык, который сделает его быстрее в следующий раз. Вы можете просто использовать шаблон вместо того, чтобы кодировать панель навигации Activity с нуля.
Android Studio предоставляет шаблоны кода, которые соответствуют рекомендациям по проектированию и разработке Android. Эти существующие шаблоны кода (доступные на Java и Kotlin) могут помочь вам быстро запустить ваш проект. Один из таких шаблонов может быть использован для создания деятельности в области навигации.
Я покажу вам, как использовать эту удобную функцию в Android Studio.
Для нового проекта запустите Android Studio.
Введите имя приложения и нажмите кнопку « Далее» .
Вы можете оставить настройки по умолчанию такими, как они есть в диалоговом окне « Целевые устройства 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