Это довольно сложно решить, поскольку NavOptions
внутренне обрабатывается удобными методами, используемыми для привязки вашего ящика к навигационной диаграмме.Первоначально я протестировал это решение с меню настроек и onOptionsItemSelected
, но основная идея должна работать и здесь.
Сначала убедитесь, что идентификаторы пунктов вашего меню соответствуют идентификаторам ваших фрагментов навигации:
<menu xmlns:android="http://schemas.android.com/apk/res/android">
...
<item android:id="@+id/example_id" ... />
</menu>
<navigation xmlns:android="http://schemas.android.com/apk/res/android" ... >
...
<fragment android:id="@+id/example_id" ... />
</navigation>
Теперь вместо использования готовых методов для подключенияв свой NavController Реализуйте NavigationView.OnNavigationItemSelectedListener
в своей деятельности NavHost и переопределите метод onNavigationItemSelected
следующим образом:
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
NavHost navHost = Navigation.findNavController(this, R.id.your_nav_host_fragment);
return NavigationUI.onNavDestinationSelected(item, navHost);
}
Это перенаправит выделение в виде навигации на вашем графике.Замените your_nav_host_fragment
идентификатором фрагмента, для которого вы установили app:defaultNavHost="true"
.
. Вы заметите, что, пока это работает, по умолчанию все равно используются анимации слайдов.Это связано с тем, что вызов NavigationUI
внутренне создает свой собственный NavOptions
со следующими настройками:
NavOptions.Builder builder = new NavOptions.Builder()
.setLaunchSingleTop(true)
.setEnterAnim(R.anim.nav_default_enter_anim)
.setExitAnim(R.anim.nav_default_exit_anim)
.setPopEnterAnim(R.anim.nav_default_pop_enter_anim)
.setPopExitAnim(R.anim.nav_default_pop_exit_anim);
К сожалению, метод еще не принимает NavOptions.Builder
в качестве аргумента, ноВы можете создать служебный класс на основе исходного кода Android, чтобы имитировать функциональность:
public class NavigationUIHelper {
public static boolean onNavDestinationSelected(@NonNull MenuItem item,
@NonNull NavController navController,
@NonNull NavOptions.Builder builder) {
if ((item.getOrder() & Menu.CATEGORY_SECONDARY) == 0) {
NavDestination destination = findStartDestination(navController.getGraph());
builder.setPopUpTo(destination.getId(), false);
}
NavOptions options = builder.build();
try {
navController.navigate(item.getItemId(), null, options);
return true;
} catch (IllegalArgumentException e) {
return false;
}
}
// Need to copy this private method as well
private static NavDestination findStartDestination(@NonNull NavGraph graph) {
NavDestination startDestination = graph;
while (startDestination instanceof NavGraph) {
NavGraph parent = (NavGraph) startDestination;
startDestination = parent.findNode(parent.getStartDestination());
}
return startDestination;
}
}
Наконец, в своей деятельности вы теперь можете заменить вызов NavigationUI на вызов, реализованный в NavigationUIHelper:
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
NavHost navHost = Navigation.findNavController(this, R.id.your_nav_host_fragment);
NavOptions.Builder builder = new NavOptions.Builder()
.setLaunchSingleTop(true)
.setEnterAnim(R.anim.custom_enter)
.setExitAnim(R.anim.custom_exit)
.setPopEnterAnim(R.anim.custom_pop_enter)
.setPopExitAnim(R.anim.custom_pop_exit);
return NavigationUIHelper.onNavDestinationSelected(item, navHost, builder);
}
Это должно позволить вам изменять анимацию перехода ящика в соответствии с вашими предпочтениями, не заменяя компонент навигации.