如何基于Kotlin+MVVM实现类似Google Assistant的透明Bottom Sheet
Kotlin MVVM 实现类Google Assistant底部弹窗方案
使用官方Material组件库的ModalBottomSheet即可快速实现目标效果,完整实现步骤如下:
步骤1:添加Material Design依赖
在Module级build.gradle文件中引入官方组件,同时确保应用主题继承自Theme.MaterialComponents.*系列:
dependencies { implementation "com.google.android.material:material:1.11.0" // 保留项目原有其他依赖 }
步骤2:编写弹窗布局文件
新建布局layout_bottom_sheet_custom.xml,按照需求添加文本、按钮控件:
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/bg_bottom_sheet_round" android:padding="24dp"> <!-- 基础信息展示文本 --> <TextView android:id="@+id/tv_base_info" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="基础信息展示区域" android:textSize="18sp" app:layout_constraintTop_toTopOf="parent"/> <!-- 快捷功能按钮 --> <Button android:id="@+id/btn_quick_func" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="16dp" android:text="快捷操作" app:layout_constraintTop_toBottomOf="@id/tv_base_info"/> <!-- 跳转全屏按钮 --> <Button android:id="@+id/btn_go_fullscreen" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="12dp" android:text="更多操作(进入完整页面)" app:layout_constraintTop_toBottomOf="@id/btn_quick_func"/> </androidx.constraintlayout.widget.ConstraintLayout>
在drawable文件夹下新建圆角背景bg_bottom_sheet_round.xml:
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <solid android:color="?attr/colorSurface"/> <corners android:topLeftRadius="24dp" android:topRightRadius="24dp"/> </shape>
步骤3:封装弹窗类适配MVVM架构
新建CustomBottomSheetFragment继承自ModalBottomSheetDialogFragment,和宿主页面共享ViewModel处理交互:
class CustomBottomSheetFragment : ModalBottomSheetDialogFragment() { // 和宿主Activity共享ViewModel实例 private val viewModel by activityViewModels<MainViewModel>() override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { return inflater.inflate(R.layout.layout_bottom_sheet_custom, container, false) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) // 基础弹窗配置 dialog?.window?.setDimAmount(0.3f) // 背景蒙层透明度 setCancelable(true) // 支持点击蒙层/返回键关闭 // 按钮点击事件交由ViewModel处理 view.findViewById<Button>(R.id.btn_go_fullscreen).setOnClickListener { viewModel.triggerFullPageNavigation() dismiss() } // 其他按钮逻辑同理配置 } }
步骤4:应用启动时弹出弹窗
在主页面MainActivity的onCreate方法中添加弹窗逻辑,同时观察ViewModel的跳转事件:
class MainActivity : AppCompatActivity() { private val viewModel by viewModels<MainViewModel>() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // 启动时弹出弹窗,savedInstanceState判空避免屏幕旋转重复弹出 if (savedInstanceState == null) { CustomBottomSheetFragment().show(supportFragmentManager, "CustomBottomSheet") } // 观察跳转全屏页面的事件 viewModel.navigateToFullPage.observe(this) { needNavigate -> if (needNavigate) { startActivity(Intent(this, FullPageActivity::class.java)) viewModel.resetNavigationFlag() } } } }
样式优化对齐Google Assistant效果
- 调用
behavior.state = BottomSheetBehavior.STATE_EXPANDED设置弹窗默认完全展开 - 自定义滑入滑出动画,更贴近Google Assistant的交互手感
- 按钮设置8dp以上圆角,用填充/描边样式区分操作优先级
- 排版保留足够留白,避免内容拥挤
参考效果:
内容的提问来源于stack exchange,提问作者Rohan Arora
相关产品推荐
相关产品推荐

