Команда разработчиков материалов в Google просто определяет функциональность вкладок в Android следующим образом:
Вкладки позволяют легко исследовать и переключаться между различными представлениями.
В этом посте вы узнаете, как отображать вкладки с помощью API TabLayout
и ViewPager
. В этом практическом уроке мы рассмотрим следующее:
- Компоненты
TabLayout
иViewPager
. - Различные режимы вкладок: прокручиваемый и фиксированный.
- Как отображать иконки вместо текста для заголовков вкладок.
- В качестве бонуса вы также узнаете, как использовать функцию шаблонов Android Studio для быстрой загрузки проекта с помощью интерфейса с вкладками.
Пример проекта для этого урока можно найти в нашем репозитории GitHub, чтобы вы могли легко следить за ним.
Предпосылки
Чтобы следовать этому руководству, вам понадобится:
- Android Studio 3.0 или выше
- Плагин Kotlin 1.1.51 или выше
Вы также можете изучить все тонкости языка Kotlin в моей серии Kotlin From Scratch .
Введение в компонент TabLayout
Согласно официальной документации Android на TabLayout
, он гласит:
TabLayout
предоставляет горизонтальный макет для отображения вкладок.
Компонент TabLayout
является одним из компонентов, представленных как часть артефактов проектирования материала. Кроме того, он также включен в библиотеку поддержки дизайна. В TabLayout
, когда вкладка выбрана или TabLayout
, пользователю TabLayout
другая страница (или фрагмент).
Компонент TabLayout
может иметь функции отображаемых вкладок одним из двух способов: фиксированным и прокручиваемым. Если вкладки зафиксированы, все вкладки будут отображаться на экране одновременно.
На приведенном ниже TabLayout
последнее официальное Android-приложение WhatsApp (на момент написания статьи), в котором используется TabLayout
с фиксированной конфигурацией режима.
В прокручиваемых вкладках, если количество вкладок становится слишком большим для экрана, пользователь может провести пальцем влево или вправо, чтобы просмотреть больше вкладок.
Вот пример TabLayout
с прокручиваемым режимом вкладок, представленный в последней версии Android-приложения News & Weather от Google.
Кроме того, информация, отображаемая на вкладке, может быть текстом, значком или комбинацией как текста, так и значка. Например, последнее приложение Twitter для Android использует значки вместо текста на каждой вкладке.
В следующих разделах мы TabLayout
в кодирование простого приложения, которое использует TabLayout
с ViewPager
. Давай прокатимся!
Дизайн — это не только то, на что он похож и что чувствует. Дизайн — это то, как он работает. — Стив Джобс
1. Создайте проект Android Studio
TabLayoutDemo
Android Studio 3 и создайте новый проект (вы можете назвать его TabLayoutDemo
) с пустым действием MainActivity
.
2. Создание фрагментов (страниц)
Мы собираемся создать TabLayout
только с тремя вкладками. Когда выбрана каждая вкладка, она отображает отдельный фрагмент или страницу Android. Итак, давайте теперь создадим три фрагмента Android для каждой из вкладок. Мы начнем с первого класса фрагментов, и вы должны следовать аналогичному процессу для остальных двух классов фрагментов — FragmentTwo.kt и FragmentThree.kt .
Вот мой FragmentOne.kt :
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
import android.os.Bundle
import android.support.v4.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
class FragmentOne : Fragment() {
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?,
savedInstanceState: Bundle?): View?
inflater!!.inflate(R.layout.fragment_one, container, false)
companion object {
fun newInstance(): FragmentOne = FragmentOne()
}
}
|
Вот также мой R.layout.fragment_one
:
01
02
03
04
05
06
07
08
09
10
11
12
13
|
<LinearLayout xmlns:android=»https://schemas.android.com/apk/res/android»
xmlns:tools=»http://schemas.android.com/tools»
android:layout_width=»match_parent»
android:layout_height=»match_parent»
android:orientation=»vertical»>
<TextView
android:layout_width=»match_parent»
android:layout_height=»match_parent»
android:text=»FragmentOne»
android:gravity=»center_vertical|center_horizontal»/>
</LinearLayout>
|
3. Добавление TabLayout и ViewPager
Чтобы начать использовать TabLayout
и ViewPager
в своем проекте, убедитесь, что вы импортируете поддержку проектирования, а также артефакт поддержки Android — поэтому добавьте их в файл build.gradle вашего модуля, чтобы импортировать их.
1
2
3
4
|
dependencies {
implementation ‘com.android.support:design:26.1.0’
implementation ‘com.android.support:support-v4:26.1.0’
}
|
Кроме того, перейдите в файл res / layout / activlty_main.xml, чтобы включить виджет TabLayout
и представление ViewPager
.
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
33
34
35
36
37
38
39
40
41
42
43
|
<?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»
android:id=»@+id/main_content»
android:layout_width=»match_parent»
android:layout_height=»match_parent»
android:fitsSystemWindows=»true»>
<android.support.design.widget.AppBarLayout
android:id=»@+id/appbar»
android:layout_width=»match_parent»
android:layout_height=»wrap_content»
android:theme=»@style/AppTheme.AppBarOverlay»>
<android.support.v7.widget.Toolbar
android:id=»@+id/toolbar»
android:layout_width=»match_parent»
android:layout_height=»?attr/actionBarSize»
android:background=»?attr/colorPrimary»
app:contentInsetStartWithNavigation=»0dp»
app:layout_scrollFlags=»scroll|enterAlways»
app:popupTheme=»@style/AppTheme.PopupOverlay»/>
<android.support.design.widget.TabLayout
android:id=»@+id/tab_layout»
style=»@style/CustomTabLayout»
android:layout_width=»match_parent»
android:layout_height=»?attr/actionBarSize»
android:layout_gravity=»left»
android:background=»@color/colorPrimary»
app:tabGravity=»fill»
app:tabMode=»fixed»/>
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id=»@+id/view_pager»
android:layout_width=»match_parent»
android:layout_height=»match_parent»
app:layout_behavior=»@string/appbar_scrolling_view_behavior»/>
</android.support.design.widget.CoordinatorLayout>
|
Здесь мы создали простой TabLayout
с идентификатором tab_layout
. В нашем TabLayout
XML вы можете видеть, что мы включили некоторые атрибуты — например, app:tabMode
который нужно fixed
и app:tabGravity
который нужно fill
. Свойство app:tabGravity
используется для настройки способа отображения элементов вкладки, чтобы они app:tabGravity
доступное пространство. Мы устанавливаем это для fill
, что будет равномерно распределять элементы по ширине TabLayout
. Обратите внимание, что это будет более заметно на более широких дисплеях, таких как планшеты.
Я также включил атрибут нашего стиля ( @style/CustomTabLayout
) в наш виджет TabLayout
.
1
2
3
4
5
6
7
|
<style name=»CustomTabLayout» parent=»Widget.Design.TabLayout»>
<item name=»tabIndicatorColor»>@android:color/white</item>
<item name=»tabIndicatorHeight»>3dp</item>
<item name=»tabBackground»>?attr/selectableItemBackground</item>
<item name=»tabTextAppearance»>@style/CustomTabTextAppearance</item>
<item name=»tabSelectedTextColor»>@android:color/white</item>
</style>
|
Мы начинаем настраивать наш TabLayout
, устанавливая значения атрибутов, которые будут применяться к TabLayout
. Вот подробности для некоторых из примененных атрибутов:
-
tabIndicatorColor
: устанавливает цвет индикатора вкладки для текущей выбранной вкладки. Это также может быть установлено программно путем вызоваsetSelectedTabIndicatorColor()
для экземпляраTabLayout
. -
tabIndicatorHeight
: устанавливает высоту индикатора вкладки для текущей выбранной вкладки. Это также может быть установлено программно путем вызоваsetSelectedTabIndicatorHeight()
для экземпляраTabLayout
. -
tabSelectedTextColor
: устанавливает цвета текста для различных состояний (нормальное, выбранное), используемых для вкладок. Эквивалентом этого атрибута в Java являетсяsetTabTextColors()
.
Сразу после создания нашего виджета TabLayout
в XML следующим представлением был ViewPager
. Официальная документация говорит о ViewPager
следующее:
Менеджер по расположению, который позволяет пользователю пролистывать страницы данных влево и вправо …
4. Создание PagerAdapter
Нам нужно создать подкласс в SampleAdapter.kt, который расширяет FragmentPagerAdapter
. Этот класс отвечает за управление различными фрагментами, которые будут отображаться на вкладках.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
|
import android.support.v4.app.Fragment
import android.support.v4.app.FragmentManager
import android.support.v4.app.FragmentPagerAdapter
class SampleAdapter(fm: FragmentManager) : FragmentPagerAdapter(fm) {
override fun getItem(position: Int): Fragment?
0 -> FragmentOne.newInstance()
1 -> FragmentTwo.newInstance()
2 -> FragmentThree.newInstance()
else -> null
}
override fun getPageTitle(position: Int): CharSequence = when (position) {
0 -> «Tab 1 Item»
1 -> «Tab 2 Item»
2 -> «Tab 3 Item»
else -> «»
}
override fun getCount(): Int = 3
}
|
Здесь мы переопределяем три метода из родительского класса: getItem()
, getCount()
и getPageTitle()
. Вот объяснения для методов:
-
getItem()
: возвращаетFragment
для определенной позиции вViewPager
. -
getCount()
: указывает, сколько страниц будет вViewPager
. -
getPageTitle()
: этот метод вызываетсяViewPager
для получения строки заголовка для описания указанной вкладки.
Например, если выбранная вкладка является первой вкладкой с заголовком "Tab 1 Item"
вкладки "Tab 1 Item"
, страница FragmentOne
будет немедленно показана пользователю.
5. Инициализация компонентов
Далее мы собираемся инициализировать экземпляры нашего TabLayout
, ViewPager
и SampleAdapter
. Инициализация будет происходить внутри 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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
import android.os.Bundle
import android.support.design.widget.TabLayout
import android.support.v4.view.ViewPager
import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.Toolbar
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
initToolbar()
val tabLayout: TabLayout = findViewById(R.id.tab_layout)
val viewPager: ViewPager = findViewById(R.id.view_pager)
val adapter = SampleAdapter(supportFragmentManager)
viewPager.adapter = adapter
tabLayout.setupWithViewPager(viewPager)
tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
override fun onTabSelected(tab: TabLayout.Tab) {
}
override fun onTabUnselected(tab: TabLayout.Tab) {
}
override fun onTabReselected(tab: TabLayout.Tab) {
}
})
}
private fun initToolbar() {
val toolbar: Toolbar = findViewById(R.id.toolbar)
setSupportActionBar(toolbar)
supportActionBar!!.title = «TabLayout Demo»
}
}
|
Мы получили ссылки на наш TabLayout
и ViewPager
из R.layout.activity_main
и инициализировали их. Мы также создали экземпляр нашего SampleAdapter
передав в качестве аргумента экземпляр FragmentManager
. Нам нужно предоставить представления для нашего ViewPager
, поэтому мы вызвали setAdapter()
и передали в него созданный нами адаптер. Наконец, мы вызвали setupWithViewPager()
для экземпляра TabLayout
чтобы выполнить некоторую работу:
- создание необходимой вкладки для каждой страницы
- настройка необходимых слушателей
Когда пользователь нажимает на вкладку, он меняет страницы в ViewPager
и показывает требуемую страницу (или Fragment
). Кроме того, пролистывание страниц обновляет выбранную вкладку. Другими словами, этот метод помогает нам позаботиться об изменении состояния прокрутки и кликах по вкладкам.
onTabSelectedListener()
используется для включения прослушивателя, который будет вызываться при изменении выбора вкладки. Мы переопределили следующие обратные вызовы:
-
onTabSelected()
: срабатывает, когда вкладка входит в выбранное состояние. -
onTabUnselected()
: вызывается, когда вкладка выходит из выбранного состояния. -
onTabReselected()
: вызывается, когда пользователь снова выбирает уже выбранную вкладку.
Обратите внимание, что мы также можем установить режим вкладки программно — вместо XML-макета — используя setTabMode()
в экземпляре TabLayout
. Мы передаем режим (фиксированный или прокручиваемый) этому методу в качестве аргументов. Например, мы можем передать TabLayout.MODE_FIXED
для фиксированного режима или TabLayout.MODE_SCROLLABLE
для режима TabLayout.MODE_SCROLLABLE
.
1
2
|
tabLayout.tabMode = TabLayout.MODE_FIXED
tabLayout.tabMode = TabLayout.MODE_SCROLLABLE
|
Обратите внимание, что если вы хотите явно создавать вкладки вместо использования вспомогательного метода setUpWithViewPager()
, вы можете вместо этого использовать newTab()
в экземпляре TabLayout
.
1
2
3
4
5
|
val tabLayout: TabLayout = findViewById(R.id.tab_layout)
tabLayout.addTab(tabLayout.newTab().setText(«Songs»))
tabLayout.addTab(tabLayout.newTab().setText(«Albums»))
tabLayout.addTab(tabLayout.newTab().setText(«Artists»))
|
Также обратите внимание, что мы можем явно создавать вкладки с помощью 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
|
<android.support.design.widget.TabLayout
android:id=»@+id/tabs»
android:layout_width=»match_parent»
android:layout_height=»wrap_content»>
<android.support.design.widget.TabItem
android:id=»@+id/tabItem»
android:layout_width=»wrap_content»
android:layout_height=»wrap_content»
android:text=»Songs»/>
<android.support.design.widget.TabItem
android:id=»@+id/tabItem2″
android:layout_width=»wrap_content»
android:layout_height=»wrap_content»
android:text=»Albums»/>
<android.support.design.widget.TabItem
android:id=»@+id/tabItem3″
android:layout_width=»wrap_content»
android:layout_height=»wrap_content»
android:text=»Artists»/>
</android.support.design.widget.TabLayout>
|
6. Тестирование приложения
Наконец, вы можете запустить приложение!
Попробуйте взаимодействовать с приложением, проведя пальцем влево или вправо и нажав вкладки.
7. Прокручиваемые вкладки
Официальные рекомендации по дизайну материалов на вкладках говорят о прокручиваемых вкладках:
Прокручиваемые вкладки отображают подмножество вкладок в любой момент. Они могут содержать более длинные ярлыки вкладок и большее количество вкладок, чем фиксированные вкладки. Прокручиваемые вкладки лучше всего использовать для просмотра контекстов в сенсорных интерфейсах, когда пользователям не нужно напрямую сравнивать ярлыки вкладок.
Давайте посмотрим, как создавать вкладки в режиме прокрутки. Я сделал заголовок для каждой вкладки длиннее, чем раньше. Вот результат в фиксированном режиме:
Вы можете видеть, что TabLayout
использовал несколько строк для отображения каждого из заголовков вкладки. В некоторых ситуациях это будет даже урезать названия! Это создает плохой пользовательский опыт, поэтому, если заголовки ваших вкладок должны быть очень длинными, вам следует рассмотреть возможность использования режима прокрутки. Также обратите внимание, что если у вас будет более четырех вкладок, рекомендуется сделать режим вкладок прокручиваемым.
Давайте app:tabMode
свойство app:tabMode
с fixed
на scrollable
.
1
2
3
|
<android.support.design.widget.TabLayout
<!— … —>
app:tabMode=»scrollable»/>
|
Помните, что вы также можете установить режим вкладки программно, как обсуждалось ранее.
8. Отображение значков вкладок
Давайте теперь рассмотрим, как заменить текст элемента вкладки значками.
01
02
03
04
05
06
07
08
09
10
11
12
13
|
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
// …
tabLayout.setupWithViewPager(viewPager)
tabLayout.getTabAt(0)!!.setIcon(android.R.drawable.ic_dialog_email)
tabLayout.getTabAt(1)!!.setIcon(android.R.drawable.ic_dialog_info)
tabLayout.getTabAt(2)!!.setIcon(android.R.drawable.ic_dialog_alert)
// …
}
// …
}
|
Здесь мы вызвали getTabAt()
для экземпляра TabLayout
. Вызов этого метода вернет вкладку с указанным индексом. Далее мы вызываем setIcon()
. Вызов этого метода установит значок, отображаемый на этой вкладке.
Я также установил режим вкладки, чтобы быть исправленным.
1
2
|
<android.support.design.widget.TabLayout
app:tabMode=»fixed»/>
|
Я все еще переопределяю getPageTitle()
внутри SampleAdapter
.
01
02
03
04
05
06
07
08
09
10
11
12
13
|
class SampleAdapter(fm: FragmentManager) : FragmentPagerAdapter(fm) {
// …
override fun getPageTitle(position: Int): CharSequence = when (position) {
0 -> «TAB 1»
1 -> «TAB 2»
2 -> «TAB 3»
else -> «»
}
// …
}
|
Вот результат:
Теперь, если вам нужны только значки, вы просто не переопределяете getPageTitle()
.
9. Бонус: использование шаблонов Android Studio
Вместо того, чтобы писать так много кода просто для создания интерфейса с вкладками или деятельности с нуля, в Android Studio 3.0 есть несколько уже существующих шаблонов кода (доступных на Java и Kotlin), которые помогут запустить ваш проект. Один такой шаблон можно использовать для создания вкладок.
Я покажу вам, как использовать эту удобную функцию в Android Studio 3.
Для нового проекта запустите Android Studio 3.
Введите имя приложения и нажмите кнопку « Далее» .
Вы можете оставить настройки по умолчанию такими, как они есть в диалоговом окне « Целевые устройства Android » Нажмите кнопку Далее еще раз.
В диалоговом окне « Добавить действие на мобильный » прокрутите вниз и выберите вкладку « Активность». Нажмите кнопку Далее после этого.
В последнем диалоговом окне прокрутите вниз до раскрывающегося меню « Стиль навигации» и выберите « Вкладки панели действий» (с ViewPager) . Наконец, нажмите кнопку Готово , чтобы принять все конфигурации.
Android Studio теперь помогла нам создать проект с вкладками. Очень круто!
Вам настоятельно рекомендуется изучить сгенерированный код.
В уже существующем проекте Android Studio, чтобы использовать этот шаблон, просто выберите «Файл»> «Активность»> «Активность с вкладками» . И выполните аналогичные шаги, которые были описаны ранее.
Шаблоны, которые входят в состав Android Studio, хороши для простых макетов и создания базовых приложений, но если вы хотите запустить свое приложение еще дальше, вы можете рассмотреть некоторые из шаблонов приложений, доступных на Envato Market .
Они значительно экономят время опытных разработчиков, помогая им сократить время создания приложения с нуля и сосредоточить свои таланты вместо этого на уникальных и настраиваемых частях создания нового приложения.
Вывод
Из этого руководства вы узнали, как создать интерфейс с вкладками в Android с помощью API TabLayout
и ViewPager
с нуля. Мы также узнали, как легко и быстро использовать шаблоны Android Studio для создания интерфейса с вкладками.
Я настоятельно рекомендую ознакомиться с официальными рекомендациями по разработке материалов для вкладок, чтобы узнать больше о том, как правильно проектировать и использовать вкладки в Android.
Чтобы узнать больше о кодировании для Android, ознакомьтесь с другими нашими курсами и учебными пособиями здесь, на Envato Tuts +!