Можно ли изменить эффект перехода от открытия фрагмента из drawerlayout с помощью компонента навигации Android. В документации по андроиду ничего нет.




Сара! Да, это возможно. Вы можете добавить свой собственный слушатель для обработки выбора элемента навигации и добавления туда анимации. Мне пришлось добавить один для других целей, но он определенно подходит для решения вашей задачи.
<?xml version = "1.0" encoding = "utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout 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:id = "@+id/drawer_layout"
android:layout_width = "match_parent"
android:layout_height = "match_parent"
android:fitsSystemWindows = "true"
tools:openDrawer = "start">
<!-- Other views can be added here, or below -->
<com.google.android.material.navigation.NavigationView
android:id = "@+id/nav_view"
android:layout_width = "wrap_content"
android:layout_height = "match_parent"
android:layout_gravity = "start"
app:menu = "@menu/menu_for_drawer" />
</androidx.drawerlayout.widget.DrawerLayout>
NavigationView по идентификатору и назначьте его переменной private NavigationView navigationView в своей деятельности, которую вы можете извлечь с помощью findViewById(R.id.nav_view). Этот шаг не является обязательным. Вы можете найти прослушиватель выбора элемента навигации view и assing без ссылки на NavigationView;navigationView.setNavigationItemSelectedListener(menuItem -> {
@IdRes
int id = menuItem.getItemId();
NavOptions.Builder optionsBuilder = new NavOptions.Builder();
switch (id) {
case R.id.first_menu_item_id: {
// Lets assume for the first menu item navigation is default
optionsBuilder
.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);
}
break;
case R.id.second_menu_item_id: {
// Lets assume for the second menu item navigation is missing
// empty here
}
break;
case R.id.thrid_menu_item_id: {
// Lets assume for the third menu item navigation is custom
optionsBuilder
.setEnterAnim(R.anim.slide_in_right)
.setExitAnim(R.anim.slide_out_left)
.setPopEnterAnim(R.anim.slide_in_left)
.setPopExitAnim(R.anim.slide_out_right);
}
break;
}
navController.navigate(id, null, optionsBuilder.build());
// Do not forget to close the drawer
// drawer.closeDrawers();
return true;
});
Это должно помочь! Приветствуются любые мысли и вопросы!
Если вас интересуют анимации, упомянутые в примере:
slide_in_left.xml<?xml version = "1.0" encoding = "utf-8"?>
<set xmlns:android = "http://schemas.android.com/apk/res/android">
<translate android:fromXDelta = "-100%" android:toXDelta = "0%"
android:fromYDelta = "0%" android:toYDelta = "0%"
android:duration = "300"/>
</set>
slide_in_right.xml<?xml version = "1.0" encoding = "utf-8"?>
<set xmlns:android = "http://schemas.android.com/apk/res/android">
<translate android:fromXDelta = "100%" android:toXDelta = "0%"
android:fromYDelta = "0%" android:toYDelta = "0%"
android:duration = "300"/>
</set>
slide_out_left.xml<?xml version = "1.0" encoding = "utf-8"?>
<set xmlns:android = "http://schemas.android.com/apk/res/android">
<translate android:fromXDelta = "0%" android:toXDelta = "-100%"
android:fromYDelta = "0%" android:toYDelta = "0%"
android:duration = "300"/>
</set>
slide_out_right.xml<?xml version = "1.0" encoding = "utf-8"?>
<set xmlns:android = "http://schemas.android.com/apk/res/android">
<translate android:fromXDelta = "0%" android:toXDelta = "100%"
android:fromYDelta = "0%" android:toYDelta = "0%"
android:duration = "300"/>
</set>
Если это решение не работает с меню ящика, попробуйте использовать его с участием следующий код.
Обратите внимание, что я поместил вызов setNavigationItemSelectedListener в конец метода из-за функций NavigationUI, иногда настройки это собственный слушатель. Это также могло быть причиной проблемы.
За функциями NavigationUI творится много всего, и если что-то не работает, проверьте реализацию функций, которые вы используете.
private void setupNavigation() {
// Set custom toolbar as action bar
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();
// Setup navigation with toolbar and drawer
NavController navController = Navigation.findNavController(this, R.id.main_nav_host_fragment);
/* The set of destinations by id considered at the top level
of your information hierarchy. The Up button will not be displayed
when on these destinations. */
Set<Integer> set = new HashSet<>(Arrays.asList(R.id.first_fragmentId_from_nav_graph, R.id.second_fragmentId_from_nav_graph, R.id.third_fragmentId_from_nav_graph));
/* Configuration options for {@link NavigationUI} methods that interact with implementations of the
app bar pattern */
AppBarConfiguration configuration = new AppBarConfiguration.Builder(set).setDrawerLayout(drawer).build();
NavigationUI.setupWithNavController(toolbar, navController, configuration);
NavigationUI.setupWithNavController(navigationView, navController);
NavigationUI.setupActionBarWithNavController(this, navController, configuration);
// And here you set the listener.
navigationView.setNavigationItemSelectedListener(...);
}
Есть несколько вызовов функций NavigationUI, таких как setupWithNavController и setupActionBarWithNavController. Причина в том, что за каждым из них добавляется еще один слушатель изменения пункта назначения к контроллеру навигации. См. addOnDestinationChangedListener для получения дополнительной информации о слушателе.
new ToolbarOnDestinationChangedListener(toolbar, configuration);NavController.OnDestinationChangedListener, которая правильно обновляет ваш вид навигации в ящике;new ActionBarOnDestinationChangedListener(activity, configuration).Эта конфигурация позволяет мне использовать одно приложение на планшете с шаблоном Master-Detail и на телефоне как обычное приложение с Drawer Menu.
Ссылки на строковые ресурсы:
<string name = "navigation_drawer_open">Open navigation drawer</string>
<string name = "navigation_drawer_close">Close navigation drawer</string>
Но они необходимы для доступности. Их очень хорошо переводить, если вы поддерживаете несколько языков. В основном все, что используется для обеспечения доступности, обычно хорошо переводить.
@tzg, я полагаю, что setNavigationItemSelectedListener не вызывается, потому что компонент навигации либо не знает о ящике, либо способ настройки навигации вызывает проблему. Я дополню ответ конфигурацией, используемой в моем проекте.
Есть способ попроще. Внутренне NavigationUI собирает NavOptions следующим образом:
if (navController.getCurrentDestination().getParent().findNode(item.getItemId())
instanceof ActivityNavigator.Destination) {
builder.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);
} else {
builder.setEnterAnim(R.animator.nav_default_enter_anim)
.setExitAnim(R.animator.nav_default_exit_anim)
.setPopEnterAnim(R.animator.nav_default_pop_enter_anim)
.setPopExitAnim(R.animator.nav_default_pop_exit_anim);
}
Вы можете просто создать эти каталоги самостоятельно и изменить значения по умолчанию. В моем случае мне пришлось создать папку animator (не anim!) В /res/ и поместить в нее 4 новых файла анимации с этими именами. Но, может быть, попробуйте обе папки, чтобы убедиться.
На данный момент он отлично работает в теме MaterialComponents: выбранный элемент ящика по-прежнему выделяется, и анимация панели приложений также работает (в отличие от некоторых других методов).
Я попробовал вашу реализацию. Кажется, это именно то, что я ищу. У меня есть меню ящика с несколькими фрагментами, в которые я хочу добавить переход анимации. Я добавил код в свой метод onCreate в MainActivity. SetNavigationItemSelectedListener не вызывается, когда я выбираю из меню ящика.