Компонент навигационной архитектуры Android - значки Nav Drawer
В настоящее время я использую компонент архитектуры Android Navigation
, но у меня проблема с моим Navigation Drawer
, Это показывает меню гамбургера, когда в моем начальном пункте назначения, но другой Fragments
показывают стрелку вверх. Я считаю, что я настроил мой navigation_graph
неправильно.
Здесь вы можете увидеть мой навигационный ящик, показывающий 2 пункта, Дом и Настройки. Находясь в любом из этих фрагментов, вы должны увидеть значок гамбургера.
Однако при переходе к фрагменту настроек отображается стрелка вверх.
navigation.graph.xml
<?xml version="1.0" encoding="utf-8"?>
<navigation 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"
app:startDestination="@id/nav_home">
<!-- Start at HomeFragment -->
<fragment
android:id="@+id/nav_home"
android:name=".HomeFragment"
android:label="@string/home">
<!-- Navigate to the Search -->
<action
android:id="@+id/action_nav_home_to_nav_search"
app:destination="@id/nav_search" />
</fragment>
<fragment
android:id="@+id/nav_settings"
android:name=".SettingsFragment"
android:label="@string/settings">
<!-- Navigate to the Search -->
<action
android:id="@+id/action_nav_settings_to_nav_search"
app:destination="@id/nav_search" />
</fragment>
<fragment
android:id="@+id/nav_search"
android:name=".SearchFragment"
android:label="@string/search" />
</navigation>
я чувствую HomeFragment
а также SettingsFragment
должно быть как-то связано, но я не уверен, как это определить.
main_drawer.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:checkableBehavior="single">
<item
android:id="@id/nav_home"
android:icon="@drawable/ic_home_white_24dp"
android:title="@string/home" />
<item
android:id="@id/nav_settings"
android:icon="@drawable/ic_settings_white_24dp"
android:title="@string/settings" />
</group>
</menu>
Основная деятельность
А потом в MainActivity
Я просто настроил это так. я звонил setupActionBarWithNavController
, но я также должен сам настроить навигационный ящик и обработать onNavigationItemSelected
,
private fun setupNavigation() {
navController = findNavController(R.id.mainNavigationFragment)
setupActionBarWithNavController(this, navController, drawer_layout)
val toggle = ActionBarDrawerToggle(
this, drawer_layout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close)
drawer_layout.addDrawerListener(toggle)
toggle.syncState()
nav_view.setNavigationItemSelectedListener(this)
}
override fun onNavigationItemSelected(item: MenuItem): Boolean {
val current = navController.currentDestination.id
if (item.itemId != current) {
navController.navigate(item.itemId)
}
drawer_layout.closeDrawers()
return true
}
build.gradle
// Navigation
implementation 'android.arch.navigation:navigation-fragment-ktx:1.0.0-alpha04'
implementation 'android.arch.navigation:navigation-ui-ktx:1.0.0-alpha04'
Благодарю.
6 ответов
В более новых альфах (у меня 1.0.0-alpha07) они добавили возможность определять topLevelDestinationIds
при звонке AppBarConfiguration
конструктор.
Поэтому я настроил свой NavController следующим образом
val navController = findNavController(R.id.nav_host_fragment)
val config = AppBarConfiguration(
setOf(
R.id.fistTopFragment,
R.id.secondTopFragment,
...
),
dr.drawerLayout
)
tb.setupWithNavController(navController, config)
куда dr
это MaterialDrawer и tb
конечно панель инструментов.
Тогда он ведет себя больше как Gmail, по крайней мере, для ActionBarDrawerToggle
задний стек все еще сохраняется. Поскольку я должен сам обрабатывать выбор элементов в MaterialDrawer, я собираюсь сократить действия в стеке назад, используя глобальные навигационные действия с включенным popTo для корневого фрагмента навигационного графа, и пока использую что-то вроде "экрана приветствия".
Другим способом может быть пользовательская обработка onBackPressed
, Вы должны удалить app:defaultNavHost="true"
от вашего фрагмента хоста в макете деятельности в первую очередь. Что-то вроде этого
override fun onBackPressed() {
val navController = findNavController(R.id.nav_host_fragment)
if (navController.currentDestination == null
|| navController.currentDestination!!.id in setOf(
R.id.fistTopFragment,
R.id.secondTopFragment,
...
)
) {
super.onBackPressed()
} else {
navController.navigateUp()
}
}
Извините за код, я все еще изучаю Kotlin, так что, вероятно, есть гораздо более приятный способ сделать это.
Боюсь, это особенность навигационной составляющей.
На панели действий также будет отображаться кнопка "Вверх", когда вы находитесь не в корневом назначении, и значок ящика в корневом назначении, автоматически анимирующийся между ними.
Если вы хотите, вы можете попробовать использовать setupWithNavController(NavigationView, NavController) и обрабатывать панель инструментов самостоятельно.
Я сделал простой пример для этого вопроса. Решение почти такое же, как ответ Всевышнего. https://github.com/isaul32/android-sunflower
Сначала создайте набор пунктов назначения высшего уровня
val topLevelDestinations = setOf(R.id.garden_fragment,
R.id.plant_list_fragment)
appBarConfiguration = AppBarConfiguration.Builder(topLevelDestinations)
.setDrawerLayout(drawerLayout)
.build()
а затем переопределить функцию onSupportNavigateUp, как это
override fun onSupportNavigateUp(): Boolean {
return NavigationUI.navigateUp(navController, appBarConfiguration)
}
Если вы хотите, вы можете попробовать использовать NavController.OnNavigatedListener и использовать приведенный ниже код для установки заголовка.
@Override
public void onNavigated(@NonNull NavController controller, @NonNull NavDestination destination) {
mActivityBinding.toolbar.setTitle(destination.getLabel());
}
Не забудьте установить метку на графике навигации.
Стрелка назад появляется на фрагментах вкладок, связанных с BottomNavigationView
это намеренное поведение. Однако не видел, чтобы он использовался "как есть" даже в известных приложениях (Instagram, Youtube с нижними вкладками). Если вы перейдете к различным нижним вкладкам в приложении Youtube, например, и нажмете опцию возврата устройства, вы заметите, что он переходит к предыдущему фрагменту вкладки и не выходит из приложения. Таким образом, фрагменты вкладок bottomnavigationview здесь не являются корневыми.
Хотите обратить внимание на дополнительные важные проблемы, с которыми вы можете столкнуться по мере продвижения вперед:
Не позволяет повторное использование фрагментов в сочетании с
BottomNavigationView
https://issuetracker.google.com/issues/110373186Если у вас есть несколько действий, кнопка вверх не перейдет к предыдущему действию https://issuetracker.google.com/issues/79993862
Однако есть несколько хуков, которые вы можете использовать для настройки поведения:
onBackPressed
- закрыть макет ящика, если он открытoverride fun onBackPressed() { if (drawerLayout.isDrawerOpen(GravityCompat.START)) { drawerLayout.closeDrawer(GravityCompat.START) } else { super.onBackPressed() } }
добавлять
navController.addOnNavigatedListener(..)
и внутри слушателя настроить значок HomeAsUpIndicatorOverride
onOptionsItemSelected
настроить меню с идентификаторомandroid.R.id.home
действиеУстановите специальный навигатор фрагментов, чтобы настроить обработку фрагментов (заменить или показать / скрыть)
navHostFragment = supportFragmentManager .findFragmentById(R.id.my_nav_host_fragment) as NavHostFragment? ?: return val customNavigator = CustomFragmentNavigator(navHostFragment.requireContext(), navHostFragment.childFragmentManager, navHostFragment.id) navHostFragment.navController.navigatorProvider.addNavigator(customNavigator) val inflater = navHostFragment.navController.navInflater val graph = inflater.inflate(R.navigation.main_nav_graph) navHostFragment.navController.graph = graph
Помните, что компонент навигационной арки все еще находится в альфа-режиме, поэтому используйте его с умом.
Я думаю, что ваши пункты меню должны быть такими:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@id/nav_home"
android:icon="@drawable/ic_home_white_24dp"
android:title="@string/home" />
<item
android:id="@id/nav_settings"
android:icon="@drawable/ic_settings_white_24dp"
android:title="@string/settings" />
</menu>
Надеюсь это поможет
Удачного кодирования...
Я полностью согласен с мнением здесь, но это часть библиотеки
setupActionBarWithNavController
Устанавливает ActionBar, возвращаемый AppCompatActivity.getSupportActionBar() для использования с NavController.
При вызове этого метода заголовок на панели действий будет автоматически обновляться при изменении места назначения (при условии, что существует допустимая метка).
Начальный пункт назначения вашего навигационного графика считается единственным пунктом назначения верхнего уровня. В пункте назначения начала вашего навигационного графика панель действий покажет значок ящика, если заданный DrawerLayout не равен NULL. На всех других направлениях на панели действий появится кнопка "Вверх". Вызовите navigateUp(NavController, DrawerLayout) для обработки кнопки "Вверх".
это для меня нарушено и не является желаемым результатом, поэтому то, что я делаю, все еще использует его с использованием вида навигации, используя
navController = Navigation.findNavController(this, R.id.nav_host);
NavigationUI.setupWithNavController(navigationView,navController);
а затем с прослушивателем, чтобы обновить заголовок и все остальное, что я хочу изменить, как это
navController.addOnNavigatedListener((controller, destination) -> {
setToolbarColour(R.color.primary);
switch (destination.getId()){
case R.id.dashBoard :
setToolbarColour(android.R.color.transparent);
break;
case R.id.requests :
toolbar.setTitle(getString(R.string.request));
break;
}
});
Затем я создаю новый график навигации для каждого из этих фрагментов, не очень, но я получаю желаемый результат