You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何开发实现Gmail安卓App同款侧边菜单栏动画效果

Gmail安卓同款侧边栏实现方案

核心使用组件

不需要同时嵌套NavigationRail和NavigationDrawer两个组件,堆叠两层视图本身就会导致过渡卡顿。Gmail的侧边栏本质是基于DrawerLayout+NavigationView自定义状态切换逻辑实现的单容器组件,同时兼顾NavigationRail的折叠态外观和NavigationDrawer的展开动画效果。

具体实现步骤

  • 基础布局搭建:根布局使用DrawerLayout,仅保留一个侧边栏容器,默认设置为折叠态宽度(通常为72dp,和标准NavigationRail宽度一致),展开态宽度设置为Material规范的侧边栏宽度(320dp,可根据屏幕尺寸自适应调整)。禁用DrawerLayout默认的滑入滑出手势和动画,避免和自定义动画冲突。
  • 统一动画驱动:使用同一个ValueAnimator控制整个过渡过程,所有属性变化绑定同一动画进度,保证过渡一致性。展开时动画同步执行三个变化:侧边栏宽度从72dp过渡到320dp、菜单项文字透明度从0渐变到1、菜单项图标从居中位置偏移到左侧位置;折叠时反向执行上述变化。
  • 状态管理:仅维护EXPANDED、COLLAPSED两种侧边栏状态,点击汉堡按钮、侧边栏滑动手势都直接触发状态切换,调用上述动画逻辑即可。
  • 手势适配:如果需要保留NavigationDrawer的边缘滑入效果,监听主内容区的边缘滑动事件,直接触发侧边栏展开动画,不需要额外弹出抽屉层。

关键代码示例

布局文件示例

<androidx.drawerlayout.widget.DrawerLayout
    android:id="@+id/drawerLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- 主内容区域 -->
    <FrameLayout
        android:id="@+id/mainContent"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <!-- 自定义侧边栏容器 -->
    <LinearLayout
        android:id="@+id/sidebarContainer"
        android:layout_width="72dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:background="?attr/colorSurface"
        android:orientation="vertical">

        <com.google.android.material.navigation.NavigationView
            android:id="@+id/navigationView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:menu="@menu/sidebar_menu"
            app:itemIconGravity="start"/>

    </LinearLayout>

</androidx.drawerlayout.widget.DrawerLayout>

状态切换动画代码

// 初始化时先禁用DrawerLayout默认抽屉行为
drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)

private fun toggleSidebar(isExpand: Boolean) {
    val collapsedWidth = resources.getDimensionPixelSize(R.dimen.sidebar_collapsed_width) // 72dp
    val expandedWidth = resources.getDimensionPixelSize(R.dimen.sidebar_expanded_width) // 320dp
    val targetWidth = if (isExpand) expandedWidth else collapsedWidth

    ValueAnimator.ofInt(sidebarContainer.width, targetWidth).apply {
        duration = 300 // 和Material Design默认抽屉动画时长保持一致
        interpolator = FastOutSlowInInterpolator()
        addUpdateListener { anim ->
            val progress = anim.animatedFraction
            // 更新侧边栏宽度
            sidebarContainer.layoutParams.width = anim.animatedValue as Int
            sidebarContainer.requestLayout()
            // 同步更新菜单项文字透明度
            for (i in 0 until navigationView.menu.size()) {
                val menuItem = navigationView.menu.getItem(i)
                // 这里可以根据需求额外调整图标偏移量
                menuItem.titleCondensed = menuItem.title
                navigationView.findViewById<TextView>(R.id.design_menu_item_text)?.alpha = if (isExpand) progress else 1 - progress
            }
        }
        start()
    }
}

内容的提问来源于stack exchange,提问作者aeroxr1

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 04:12:04