簡體   English   中英

具有從 Drawerlayout 過渡的 Android 導航組件

[英]Android Navigation Component with Transition from Drawerlayout

是否可以使用android導航組件從抽屜布局中打開片段來更改過渡效果。 android 文檔中沒有任何內容。

莎拉! 對的,這是可能的。 您可以添加自定義偵聽器來處理導航項選擇並在那里添加動畫。 為了其他目的,我不得不自己添加一個,但它絕對適合作為您任務的解決方案。

如何:

  1. 添加帶抽屜的布局。 例子:
<?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>
  1. 按 ID 查找NavigationView並將其分配給活動中的變量private NavigationView navigationView ,您可以使用findViewById(R.id.nav_view)提取該變量。 此步驟是可選的。 您可以在不持有對 NavigationView 的引用的情況下找到視圖和輔助導航項選擇偵聽器;
  2. 設置導航項選擇偵聽器:
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>

更新(2020 年 3 月 28 日)

如果此解決方案不適用於 Drawer Menu,請嘗試將其以下代碼一起使用。

請注意,由於NavigationUI函數有時會設置它自己的 listener ,因此我在方法末尾放置了setNavigationItemSelectedListener調用。 這也可能是問題的原因。

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函數,例如setupWithNavControllersetupActionBarWithNavController 原因是在每一個后面都添加了一個目的地更改監聽器到導航控制器。 有關偵聽器的更多信息,請參閱addOnDestinationChangedListener

  1. 第一次調用添加了new ToolbarOnDestinationChangedListener(toolbar, configuration)
  2. 第二次調用添加了NavController.OnDestinationChangedListener自定義實現,以正確更新抽屜中的導航視圖;
  3. 第三次調用添加了new ActionBarOnDestinationChangedListener(activity, configuration)

這種配置允許我在具有主從模式的平板電腦上使用單個應用程序,並在手機上作為帶有抽屜菜單的常用應用程序使用。

引用的字符串資源只是:

<string name="navigation_drawer_open">Open navigation drawer</string>
<string name="navigation_drawer_close">Close navigation drawer</string>

但它們是可訪問性所必需的。 如果您支持多種語言,翻譯它們非常好。 基本上任何用於可訪問性的東西通常都可以很好地翻譯。

有一個更簡單的方法。 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);
    }

您可以自己創建這些目錄並覆蓋默認值。 就我而言,我必須在/res/創建animator文件夾(不是anim !),並在其中放置 4 個具有這些名稱的新動畫文件。 但也許可以嘗試兩個文件夾以確保。
目前它在 MaterialComponents 主題中完美運行:所選的抽屜項目仍然突出顯示,並且應用欄動畫仍然有效(與其他一些方法不同)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM