如何在Android中创建可折叠展开的Persistent Bottom Sheet
实现可折叠且不完全隐藏的Persistent Bottom Sheet
核心思路
要实现不会完全消失的Persistent Bottom Sheet,关键是控制两个核心属性:
- 设置折叠时的固定最小高度,确保组件始终保持可见
- 禁用完全隐藏状态,限制组件仅在「折叠」和「展开」两种状态间切换
方案一:Android Jetpack Compose(Material 3)
使用BottomSheetScaffold配合rememberBottomSheetState,通过参数配置实现需求:
import androidx.compose.foundation.layout.* import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.ExpandMore import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp @OptIn(ExperimentalMaterial3Api::class) @Composable fun PersistentBottomSheetDemo() { // 定义BottomSheet状态:跳过隐藏状态,初始为部分展开 val bottomSheetState = rememberBottomSheetState( initialValue = BottomSheetValue.PartiallyExpanded, skipHiddenState = true ) val scope = rememberCoroutineScope() BottomSheetScaffold( sheetContent = { Column( modifier = Modifier .fillMaxWidth() .padding(16.dp), horizontalAlignment = Alignment.CenterHorizontally ) { // 顶部拖拽手柄 Icon( imageVector = Icons.Default.ExpandMore, contentDescription = "切换展开/折叠", modifier = Modifier.padding(bottom = 8.dp) ) Text(text = "折叠状态展示内容") Spacer(modifier = Modifier.height(16.dp)) // 手动切换按钮 Button(onClick = { scope.launch { if (bottomSheetState.isPartiallyExpanded) { bottomSheetState.expand() } else { bottomSheetState.partialExpand() } } }) { Text(if (bottomSheetState.isPartiallyExpanded) "展开" else "折叠") } // 展开状态额外内容 if (bottomSheetState.isExpanded) { Spacer(modifier = Modifier.height(16.dp)) Text(text = "展开状态下的更多内容") // 可添加任意组件 } } }, sheetState = bottomSheetState, // 设置折叠时的固定高度 sheetPeekHeight = 120.dp, topBar = { TopAppBar(title = { Text("Persistent Bottom Sheet Demo") }) } ) { innerPadding -> // 主内容区域 Column( modifier = Modifier .fillMaxSize() .padding(innerPadding) .padding(16.dp), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ) { Text(text = "主内容展示区") } } }
关键参数说明:
skipHiddenState = true:禁止BottomSheet进入完全隐藏状态sheetPeekHeight:定义折叠时的最小显示高度,可根据需求调整数值
方案二:原生Android View系统(Material Design)
使用BottomSheetBehavior配置布局属性,实现持久化效果:
布局文件示例
<androidx.coordinatorlayout.widget.CoordinatorLayout 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="match_parent"> <!-- 主内容容器 --> <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent"> <!-- 你的主内容视图 --> </FrameLayout> <!-- Persistent Bottom Sheet --> <LinearLayout android:id="@+id/bottom_sheet" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="16dp" app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior"> <!-- 拖拽手柄 --> <View android:layout_width="40dp" android:layout_height="4dp" android:layout_gravity="center_horizontal" android:background="@drawable/bottom_sheet_handle"/> <!-- 折叠状态内容 --> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="折叠状态展示内容"/> <!-- 展开状态内容(默认隐藏) --> <LinearLayout android:id="@+id/expanded_content" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:visibility="gone"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="展开状态下的更多内容"/> </LinearLayout> <!-- 状态切换按钮 --> <Button android:id="@+id/toggle_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="展开"/> </LinearLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>
代码逻辑配置
val bottomSheet = findViewById<LinearLayout>(R.id.bottom_sheet) val expandedContent = findViewById<LinearLayout>(R.id.expanded_content) val toggleBtn = findViewById<Button>(R.id.toggle_btn) val behavior = BottomSheetBehavior.from(bottomSheet).apply { // 设置折叠时的最小高度 peekHeight = 120 // 禁止完全隐藏 isHideable = false } // 状态切换回调 behavior.addBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() { override fun onStateChanged(bottomSheet: View, newState: Int) { when (newState) { BottomSheetBehavior.STATE_EXPANDED -> { toggleBtn.text = "折叠" expandedContent.visibility = View.VISIBLE } BottomSheetBehavior.STATE_COLLAPSED -> { toggleBtn.text = "展开" expandedContent.visibility = View.GONE } else -> {} } } override fun onSlide(bottomSheet: View, slideOffset: Float) { // 可选:滑动时的动画处理 } }) // 按钮手动切换状态 toggleBtn.setOnClickListener { behavior.state = if (behavior.state == BottomSheetBehavior.STATE_COLLAPSED) { BottomSheetBehavior.STATE_EXPANDED } else { BottomSheetBehavior.STATE_COLLAPSED } }
关键配置说明:
peekHeight:设置折叠时的固定高度isHideable = false:阻止BottomSheet完全隐藏
内容的提问来源于stack exchange,提问作者arunava161292
相关产品推荐
相关产品推荐

