如何为Navigation Drawer汉堡图标添加切换动画(无需自定义ActionBar)
问题描述
复习一年前学习的纳米学位视频巩固知识时,遇到Navigation组件项目的问题:使用MVVM模式+Navigation Drawer搭配汉堡图标,点击汉堡仅能打开抽屉,再次点击无法关闭。此前用Flutter时,系统会自动在汉堡图标和返回键间切换并附带过渡动画,希望在Android项目中实现该效果,且不自定义ActionBar。
项目相关代码
activity_main.xml
<androidx.drawerlayout.widget.DrawerLayout android:id="@+id/drawerLayout" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <fragment android:id="@+id/myNavHostFragment" android:name="androidx.navigation.fragment.NavHostFragment" android:layout_width="match_parent" android:layout_height="match_parent" app:defaultNavHost="true" app:navGraph="@navigation/navigation" /> </LinearLayout> <com.google.android.material.navigation.NavigationView android:id="@+id/navView" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="start" app:headerLayout="@layout/nav_header" app:menu="@menu/navdrawer_menu" /> </androidx.drawerlayout.widget.DrawerLayout>
MainActivity.kt(原代码)
class MainActivity : AppCompatActivity() { private lateinit var drawerLayout: DrawerLayout private lateinit var appBarConfiguration : AppBarConfiguration override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val binding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main) drawerLayout = binding.drawerLayout val navController = this.findNavController(R.id.myNavHostFragment) NavigationUI.setupActionBarWithNavController(this, navController, drawerLayout) appBarConfiguration = AppBarConfiguration(navController.graph, drawerLayout) // prevent nav gesture if not on start destination navController.addOnDestinationChangedListener { nc: NavController, nd: NavDestination, bundle: Bundle? -> if (nd.id == nc.graph.startDestination) { drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED) } else { drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED) } } NavigationUI.setupWithNavController(binding.navView, navController) } override fun onSupportNavigateUp(): Boolean { val navController = this.findNavController(R.id.myNavHostFragment) return NavigationUI.navigateUp(navController, appBarConfiguration) } }
解决方案
无需自定义ActionBar,仅需调整AppBarConfiguration的初始化顺序,依托Navigation组件官方API即可实现需求:
修改后的MainActivity.kt代码
class MainActivity : AppCompatActivity() { private lateinit var drawerLayout: DrawerLayout private lateinit var appBarConfiguration: AppBarConfiguration override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val binding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main) drawerLayout = binding.drawerLayout val navController = this.findNavController(R.id.myNavHostFragment) // 先初始化AppBarConfiguration,再绑定ActionBar appBarConfiguration = AppBarConfiguration(navController.graph, drawerLayout) NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration) // 页面切换时控制抽屉手势 navController.addOnDestinationChangedListener { nc: NavController, nd: NavDestination, _: Bundle? -> if (nd.id == nc.graph.startDestination) { drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED) } else { drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED) } } NavigationUI.setupWithNavController(binding.navView, navController) } override fun onSupportNavigateUp(): Boolean { val navController = this.findNavController(R.id.myNavHostFragment) return NavigationUI.navigateUp(navController, appBarConfiguration) } }
原理说明
- 图标自动切换与动画:
AppBarConfiguration会根据当前页面是否为导航图起始目的地,自动在汉堡图标和返回键间切换,且自带系统过渡动画。 - 汉堡图标开关抽屉:传入正确配置的
AppBarConfiguration后,setupActionBarWithNavController会自动处理汉堡图标的点击逻辑——抽屉打开状态下再次点击即可关闭。 - 复用系统ActionBar:所有逻辑基于Navigation组件官方实现,无需自定义ActionBar,完全复用系统原生控件功能。
内容的提问来源于stack exchange,提问作者Omar A. Khaled
相关产品推荐
相关产品推荐

