Это вторая серия статей MAD Skills по навигации. В этой статье мы рассмотрим другой вариант использования, в котором компоненты пользовательского интерфейса, такие как панель действий, нижние вкладки или ящик, используются для навигации между различными частями приложения. Если вы предпочитаете использовать этот контент в видеоформате, посмотрите его здесь:
В предыдущей навигации серии , Chet разработала приложение для отслеживания пончики . Но что хорошо сочетается с пончиком? (кроме второго пончика) : Кофе! Поэтому я решил добавить функцию отслеживания кофе.
Мне нужно добавить больше пунктов назначения в приложение, поэтому было бы неплохо добавить панель навигации или нижние вкладки, чтобы помочь пользователям ориентироваться. Но как нам интегрировать навигацию с этими компонентами пользовательского интерфейса? Через прослушиватели кликов для ручного запуска действий навигации?
Нет! Слушателей не требуется. Вместо этого NavigationUIкласс может помочь вам перемещаться между разными пунктами назначения, сопоставляя пункты назначения и идентификаторы меню. Давайте погрузимся и посмотрим, как это работает.
Чтобы добавить эту функцию, я копирую классы, связанные с пончиками, в новый пакет и переименовываю их. Возможно, это не лучший подход для реального приложения, но он помогает нам быстро добавить функцию отслеживания кофе в существующее приложение. Если вы хотите продолжить, вы можете проверить это репо, которое для начала содержит все изменения в приложении Donut Tracker NavigationUI.
С этими изменениями я также обновляю навигационный граф, добавляя новые пункты назначения и действия от coffeeFragmentдо coffeeDialogFragmentи от selectionFragmentдо donutFragment. Я буду использовать эти идентификаторы назначения позже;)
С обновленным навигационным графиком мы можем начать связывать все вместе и включить навигацию SelectionFragment!
В настоящее время в приложении есть меню параметров, которое… ничего не делает. Чтобы он что-то сделал, в onOptionsItemSelected()функции мне нужно вызвать onNavDestinationSelected()выбранный пункт меню и передать файл navController. Эта функция будет перемещаться к назначению, связанному с данным, MenuItemпока пункт назначения и MenuItem ids совпадают.
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return item.onNavDestinationSelected(
findNavController(R.id.nav_host_fragment)
) || super.onOptionsItemSelected(item)
}
<menu 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"
tools:context="com.android.samples.donuttracker.MainActivity">
<item
android:id="@+id/selectionFragment"
android:orderInCategory="100"
android:title="@string/action_settings"
app:showAsAction="never" />
</menu>
Теперь приложение переходит к, selectionFragmentно заголовок остается прежним. Мы хотели бы, чтобы заголовок был обновлен и отображал кнопку «Назад», когда мы находимся на странице selectionFragment.
Сначала мне нужно добавить AppBarConfigurationобъект, который используется NavigationUIдля управления поведением кнопки навигации в верхнем левом углу вашего приложения.
appBarConfiguration = AppBarConfiguration(navController.graph)
По умолчанию начальная точка назначения вашего приложения является единственной конечной точкой верхнего уровня, но вы можете определить несколько мест назначения верхнего уровня. Например, в нашем приложении я могу добавить как направления, так donutListи coffeeListпункты назначения в качестве пунктов назначения верхнего уровня.
Затем я иду в MainActivityкласс, получить экземпляр navController, а toolbarи Validate ли setSupportActionBar()называется функцией. Я также обновляю ссылку на панель инструментов, переданную этой функции.
val navHostFragment = supportFragmentManager.findFragmentById(
R.id.nav_host_fragment
) as NavHostFragment
navController = navHostFragment.navController
val toolbar = binding.toolbar
setSupportActionBar(toolbar)
setupActionBarWithNavController(navController, appBarConfiguration)
override fun onSupportNavigateUp(): Boolean {
return findNavController(R.id.nav_host_fragment).navigateUp(
appBarConfiguration
)
}
Пока это выглядит неплохо, но у приложения нет возможности перейти к coffeeListфрагменту. Я исправлю это в следующий раз!
Начну с добавления нижних вкладок. Для этого я добавляю bottom_nav_menu.xmlи объявляю два пункта меню. NavigationUIполагается на MenuItem ids для соответствия адресатам ids из навигационного графа. Я также установил значки и заголовок для каждого пункта назначения.
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@id/donutList"
android:icon="@drawable/donut_with_sprinkles"
android:title="@string/donut_name" />
<item
android:id="@id/coffeeList"
android:icon="@drawable/coffee_cup"
android:title="@string/coffee_name" />
</menu>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_nav_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:menu="@menu/bottom_nav_menu" />
private fun setupBottomNavMenu(navController: NavController) {
val bottomNav = findViewById<BottomNavigationView>(
R.id.bottom_nav_view
)
bottomNav?.setupWithNavController(navController)
}
Это выглядит великолепно, но если у вашего устройства большой экран, нижние вкладки могут не обеспечивать наилучшего взаимодействия с пользователем. Чтобы исправить это, я воспользуюсь другим файлом макета, в котором есть w960dpквалификатор для более крупных / более широких устройств.
Этот макет уже есть Toolbarи FragmentContainerViewаналогично по умолчанию activity_mainмакета. Мне нужно добавить, NavigationViewа также добавить nav_drawer_menuв качестве menuатрибута NavigationView. Затем я добавлю разделитель между символами NavigationViewи FragmentContainerView.
<RelativeLayout
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="com.android.samples.donuttracker.MainActivity">
<com.google.android.material.navigation.NavigationView
android:id="@+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentStart="true"
app:elevation="0dp"
app:menu="@menu/nav_drawer_menu" />
<View
android:layout_width="1dp"
android:layout_height="match_parent"
android:layout_toEndOf="@id/nav_view"
android:background="?android:attr/listDivider" />
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:background="@color/colorPrimary"
android:layout_toEndOf="@id/nav_view"
android:theme="@style/ThemeOverlay.MaterialComponents.Dark.ActionBar" />
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/toolbar"
app:defaultNavHost="true"
android:layout_toEndOf="@id/nav_view"
app:navGraph="@navigation/nav_graph" />
</RelativeLayout>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:id="@+id/primary">
<item
android:id="@id/donutList"
android:icon="@drawable/donut_with_sprinkles"
android:title="@string/donut_name" />
<item
android:id="@id/coffeeList"
android:icon="@drawable/coffee_cup"
android:title="@string/coffee_name" />
</group>
<item
android:id="@+id/selectionFragment"
android:title="@string/action_settings" />
</menu>
private fun setupNavigationMenu(navController: NavController){
val sideNavView = findViewById<NavigationView>(R.id.nav_view)
sideNavView?.setupWithNavController(navController)
}
Обратите внимание, как стрелка назад автоматически отображается в левом верхнем углу при навигации. Если вы хотите, вы можете изменить, AppBarConfigurationчтобы включить в CoffeeListкачестве пункта назначения верхнего уровня.
Вот и все! Хорошо, по крайней мере, на этот раз. Приложению Donut Tracker не нужны были нижние вкладки или панель навигации, но новые функции и пункты назначения очень NavigationUIпомогли нам организовать навигацию в приложении.
На самом деле нам не нужно было много делать, кроме добавления компонентов пользовательского интерфейса и сопоставления MenuItemпунктов назначения idи. Вы можете просмотреть полный код и сравнить изменения с кодом статера.
Пошаговое руководство по переходу с Dagger на Hilt в многомодульном проекте. Структура проекта Для визуализации проекта он содержит несколько модулей NetworkModule, StorageModule, CommonModule, FeatureModule и т. д.
Google недавно обновил свое приложение клавиатуры Gboard для Android, включив новый макет, оптимизированный для планшетов. Сегодня утром я заметил, что мне трудно печатать, и при дальнейшем осмотре я понял, что клавиатура была заменена.
Сколько раз вы, не задумываясь, выбрасывали пластиковую бутылку, стеклянную банку, алюминиевую банку или пакет экологически чистой энергии? Сколько раз вы хотели получить что-то взамен за их переработку? Если вы похожи на большинство людей, ответ, вероятно, много раз. Переработка часто рассматривается как хлопотное дело, рутинная работа или обязанность, не приносящая немедленных или ощутимых выгод.
Вчера мы закрыли двери конкурса песни «Евровидение» в этом году блестящим, хаотичным грандиозным финалом, в котором шведская певица Лорин забрала домой трофей, став первой женщиной, выигравшей дважды, и вернув корону Швеции спустя 50 лет после того, как ABBA выиграла конкурс. с «Ватерлоо». Они стали одним из крупнейших исполнителей в каноне поп-музыки.
В современном взаимосвязанном мире угроза кибератак более распространена, чем когда-либо. Киберпреступники и государственные деятели постоянно стремятся использовать уязвимости и украсть ценные данные, подвергая организации любого размера значительному риску.
«Привет, Siri, включи Me Dive Оливии Дин». В мае 2021 года я начал стажировку в Future Academy Africa в Акуре, Нигерия.