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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 02:58:27