Android Compose 框架的对话框与反馈模块之底部表单深入分析(五十)

153 阅读10分钟

Android Compose 框架的对话框与反馈模块之底部表单深入分析

一、引言

1.1 Android Compose 概述

Android Compose 是 Google 推出的用于构建 Android 原生界面的现代声明式 UI 工具包。它摒弃了传统 Android 开发中基于 XML 和 Java 的繁琐方式,而是采用 Kotlin 语言以声明式的方式描述 UI。这种方式使得代码更加简洁、易于维护,并且能够实现高效的 UI 渲染和交互。在 Android Compose 中,UI 被视为状态的函数,当状态发生变化时,Compose 会自动重新计算并更新 UI,大大简化了 UI 开发的流程。

1.2 底部表单在 Android 应用中的重要性

底部表单(Bottom Sheet)是一种常见的 UI 组件,它通常从屏幕底部滑出,用于显示额外的选项、信息或操作。底部表单在 Android 应用中具有重要的作用,它可以在不占用过多屏幕空间的情况下,为用户提供更多的交互选项。例如,在音乐播放应用中,底部表单可以用于显示歌曲的详细信息、播放列表等;在社交应用中,底部表单可以用于发布动态、选择图片等。底部表单的使用可以提高用户体验,使应用的交互更加便捷和流畅。

1.3 本文目标

本文将深入分析 Android Compose 框架中底部表单的实现原理、使用方法和源码细节。通过详细的代码示例和源码解读,帮助开发者全面了解如何在 Android Compose 中创建、定制和管理底部表单,以及如何处理底部表单与用户的交互。同时,还会对底部表单的性能优化和兼容性问题进行探讨,为开发者在实际项目中使用底部表单提供参考。

二、底部表单的基本使用

2.1 创建简单的底部表单

在 Android Compose 中,我们可以使用 ModalBottomSheetLayout 和 ModalBottomSheetState 来创建一个简单的底部表单。以下是一个示例代码:

kotlin

import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview

// 定义一个可组合函数,用于展示包含底部表单的界面
@Composable
fun SimpleBottomSheetExample() {
    // 创建一个可变的布尔状态,用于控制底部表单的显示和隐藏
    val sheetState = rememberModalBottomSheetState(
        initialValue = ModalBottomSheetValue.Hidden // 初始状态为隐藏
    )
    // 创建一个可变的状态,用于控制是否显示底部表单
    val scope = rememberCoroutineScope()
    var showBottomSheet by remember { mutableStateOf(false) }

    // 使用 ModalBottomSheetLayout 组件来包裹内容和底部表单
    ModalBottomSheetLayout(
        sheetState = sheetState, // 传入底部表单的状态
        sheetContent = {
            // 底部表单的内容
            Column(
                modifier = Modifier.padding(16.dp)
            ) {
                // 底部表单中的文本
                Text(text = stringResource(R.string.bottom_sheet_title))
                // 底部表单中的按钮
                Button(
                    onClick = {
                        // 点击按钮时隐藏底部表单
                        scope.launch { sheetState.hide() }
                    }
                ) {
                    Text(text = stringResource(R.string.close_bottom_sheet))
                }
            }
        }
    ) {
        // 主界面的内容
        Column(
            modifier = Modifier
               .fillMaxSize()
               .padding(16.dp)
        ) {
            // 主界面中的按钮,点击时显示底部表单
            Button(
                onClick = {
                    showBottomSheet = true
                    // 启动协程来显示底部表单
                    scope.launch { sheetState.show() }
                }
            ) {
                Text(text = stringResource(R.string.show_bottom_sheet))
            }
        }
    }
}

// 预览函数,用于在 Android Studio 中预览界面
@Preview(showBackground = true)
@Composable
fun SimpleBottomSheetExamplePreview() {
    SimpleBottomSheetExample()
}

2.2 代码解释

  • 状态管理

    • sheetState:使用 rememberModalBottomSheetState 函数创建一个底部表单的状态对象,初始状态为 Hidden,表示底部表单默认是隐藏的。
    • showBottomSheet:一个可变的布尔状态,用于控制是否显示底部表单。
    • scope:使用 rememberCoroutineScope 创建一个协程作用域,用于在点击按钮时启动协程来显示或隐藏底部表单。
  • ModalBottomSheetLayout 组件:这是创建底部表单的核心组件,它接受两个主要参数:

    • sheetState:底部表单的状态对象,用于控制底部表单的显示和隐藏。
    • sheetContent:底部表单的内容,是一个可组合函数,用于定义底部表单中显示的 UI 元素。
  • 主界面内容:在 ModalBottomSheetLayout 的内容部分,我们创建了一个按钮,点击该按钮时,会将 showBottomSheet 状态设置为 true,并启动协程调用 sheetState.show() 方法来显示底部表单。

  • 底部表单内容:在 sheetContent 中,我们创建了一个 Column 布局,包含一个文本和一个按钮。点击按钮时,会启动协程调用 sheetState.hide() 方法来隐藏底部表单。

2.3 运行效果

当用户点击主界面中的 “Show Bottom Sheet” 按钮时,底部表单会从屏幕底部滑出,显示标题和关闭按钮。用户点击关闭按钮时,底部表单会滑回屏幕底部隐藏起来。

三、底部表单的源码分析

3.1 ModalBottomSheetLayout 组件的源码结构

ModalBottomSheetLayout 组件的源码位于 androidx.compose.material 包中。以下是简化后的源码结构:

kotlin

@Composable
fun ModalBottomSheetLayout(
    sheetState: ModalBottomSheetState, // 底部表单的状态
    sheetContent: @Composable () -> Unit, // 底部表单的内容
    modifier: Modifier = Modifier, // 修饰符
    scrimColor: Color = ModalBottomSheetDefaults.scrimColor, // 遮罩层颜色
    content: @Composable () -> Unit // 主界面内容
) {
    // 创建一个 Box 布局,用于包裹主界面内容和底部表单
    Box(modifier = modifier) {
        // 主界面内容
        content()

        // 创建一个 Backdrop 组件,用于处理遮罩层和触摸事件
        Backdrop(
            visible = sheetState.isVisible, // 是否显示遮罩层
            color = scrimColor, // 遮罩层颜色
            onClick = {
                if (sheetState.isVisible) {
                    // 点击遮罩层时隐藏底部表单
                    LaunchedEffect(Unit) {
                        sheetState.hide()
                    }
                }
            }
        )

        // 创建一个 BottomSheet 组件,用于显示底部表单内容
        BottomSheet(
            state = sheetState, // 底部表单的状态
            modifier = Modifier.fillMaxWidth(), // 底部表单的修饰符
            content = sheetContent // 底部表单的内容
        )
    }
}

3.2 源码解释

  • Box 布局:作为根布局,用于包裹主界面内容、遮罩层和底部表单。
  • Backdrop 组件:用于处理遮罩层和触摸事件。当底部表单显示时,会显示一个半透明的遮罩层,点击遮罩层时会隐藏底部表单。
  • BottomSheet 组件:用于显示底部表单的内容,它接受底部表单的状态和内容作为参数。

3.3 BottomSheet 组件的源码分析

BottomSheet 组件的源码如下:

kotlin

@Composable
private fun BottomSheet(
    state: ModalBottomSheetState, // 底部表单的状态
    modifier: Modifier = Modifier, // 修饰符
    content: @Composable () -> Unit // 底部表单的内容
) {
    // 创建一个 AnimatedVisibility 组件,用于实现底部表单的显示和隐藏动画
    AnimatedVisibility(
        visible = state.isVisible, // 是否显示底部表单
        enter = slideInVertically(
            initialOffsetY = { it }, // 初始偏移量为整个高度
            animationSpec = spring(
                dampingRatio = Spring.DampingRatioLowBouncy, // 弹簧阻尼比
                stiffness = Spring.StiffnessLow // 弹簧刚度
            )
        ),
        exit = slideOutVertically(
            targetOffsetY = { it }, // 目标偏移量为整个高度
            animationSpec = spring(
                dampingRatio = Spring.DampingRatioLowBouncy,
                stiffness = Spring.StiffnessLow
            )
        )
    ) {
        // 创建一个 Surface 组件,用于显示底部表单的背景
        Surface(
            modifier = modifier
               .fillMaxWidth()
               .wrapContentHeight()
               .align(Alignment.BottomCenter), // 底部居中对齐
            shape = MaterialTheme.shapes.large.copy(
                topStart = RoundedCornerShape(16.dp),
                topEnd = RoundedCornerShape(16.dp)
            ), // 圆角形状
            elevation = 16.dp // 阴影高度
        ) {
            // 底部表单的内容
            content()
        }
    }
}

3.4 源码解释

  • AnimatedVisibility 组件:用于实现底部表单的显示和隐藏动画。使用 slideInVertically 和 slideOutVertically 动画效果,使底部表单从屏幕底部滑入和滑出。
  • Surface 组件:用于显示底部表单的背景,设置了圆角形状和阴影效果,增强了底部表单的视觉效果。

四、定制底部表单

4.1 定制底部表单的样式

可以通过修改 Surface 组件的属性来定制底部表单的样式,例如背景颜色、圆角大小、阴影高度等。以下是一个定制样式的示例代码:

kotlin

import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp

// 定义一个可组合函数,用于展示定制样式的底部表单
@Composable
fun CustomStyledBottomSheet() {
    val sheetState = rememberModalBottomSheetState(
        initialValue = ModalBottomSheetValue.Hidden
    )
    val scope = rememberCoroutineScope()
    var showBottomSheet by remember { mutableStateOf(false) }

    ModalBottomSheetLayout(
        sheetState = sheetState,
        sheetContent = {
            // 定制样式的底部表单内容
            Surface(
                modifier = Modifier
                   .fillMaxWidth()
                   .wrapContentHeight(),
                shape = MaterialTheme.shapes.large.copy(
                    topStart = RoundedCornerShape(24.dp),
                    topEnd = RoundedCornerShape(24.dp)
                ), // 增大圆角大小
                color = Color.LightGray, // 背景颜色为浅灰色
                elevation = 24.dp // 增大阴影高度
            ) {
                Column(
                    modifier = Modifier.padding(16.dp)
                ) {
                    Text(text = stringResource(R.string.bottom_sheet_title))
                    Button(
                        onClick = {
                            scope.launch { sheetState.hide() }
                        }
                    ) {
                        Text(text = stringResource(R.string.close_bottom_sheet))
                    }
                }
            }
        }
    ) {
        Column(
            modifier = Modifier
               .fillMaxSize()
               .padding(16.dp)
        ) {
            Button(
                onClick = {
                    showBottomSheet = true
                    scope.launch { sheetState.show() }
                }
            ) {
                Text(text = stringResource(R.string.show_bottom_sheet))
            }
        }
    }
}

// 预览函数,用于在 Android Studio 中预览界面
@Preview(showBackground = true)
@Composable
fun CustomStyledBottomSheetPreview() {
    CustomStyledBottomSheet()
}

4.2 代码解释

  • Surface 组件:在 sheetContent 中,我们自定义了 Surface 组件的属性,包括 shapecolor 和 elevation,以实现定制的样式。

    • shape:增大了圆角大小,使底部表单的顶部更加圆润。
    • color:将背景颜色设置为浅灰色,改变了底部表单的外观。
    • elevation:增大了阴影高度,增强了底部表单的立体感。

4.3 定制底部表单的内容

除了样式,还可以定制底部表单的内容,例如添加更多的 UI 元素、使用不同的布局等。以下是一个定制内容的示例代码:

kotlin

import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp

// 定义一个可组合函数,用于展示定制内容的底部表单
@Composable
fun CustomContentBottomSheet() {
    val sheetState = rememberModalBottomSheetState(
        initialValue = ModalBottomSheetValue.Hidden
    )
    val scope = rememberCoroutineScope()
    var showBottomSheet by remember { mutableStateOf(false) }

    ModalBottomSheetLayout(
        sheetState = sheetState,
        sheetContent = {
            Column(
                modifier = Modifier
                   .fillMaxWidth()
                   .padding(16.dp)
            ) {
                // 底部表单的标题
                Text(
                    text = stringResource(R.string.bottom_sheet_title),
                    style = MaterialTheme.typography.h6
                )
                // 底部表单的分隔线
                Divider(
                    modifier = Modifier
                       .fillMaxWidth()
                       .padding(top = 8.dp, bottom = 16.dp)
                )
                // 底部表单的选项列表
                Column {
                    for (i in 1..5) {
                        Text(
                            text = "Option $i",
                            modifier = Modifier
                               .fillMaxWidth()
                               .padding(vertical = 8.dp),
                            style = MaterialTheme.typography.body1
                        )
                    }
                }
                // 底部表单的关闭按钮
                Button(
                    onClick = {
                        scope.launch { sheetState.hide() }
                    },
                    modifier = Modifier
                       .fillMaxWidth()
                       .padding(top = 16.dp)
                ) {
                    Text(text = stringResource(R.string.close_bottom_sheet))
                }
            }
        }
    ) {
        Column(
            modifier = Modifier
               .fillMaxSize()
               .padding(16.dp)
        ) {
            Button(
                onClick = {
                    showBottomSheet = true
                    scope.launch { sheetState.show() }
                }
            ) {
                Text(text = stringResource(R.string.show_bottom_sheet))
            }
        }
    }
}

// 预览函数,用于在 Android Studio 中预览界面
@Preview(showBackground = true)
@Composable
fun CustomContentBottomSheetPreview() {
    CustomContentBottomSheet()
}

4.4 代码解释

  • Column 布局:在 sheetContent 中,使用 Column 布局来组织底部表单的内容。

    • Text 组件:用于显示标题和选项列表。
    • Divider 组件:用于添加分隔线,增强内容的层次感。
    • Button 组件:用于关闭底部表单。

五、底部表单的交互处理

5.1 处理底部表单的显示和隐藏事件

在前面的示例中,我们已经看到了如何通过点击按钮来显示和隐藏底部表单。除了按钮点击事件,还可以处理其他事件,例如手势滑动。以下是一个处理手势滑动的示例代码:

kotlin

import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.gestures.draggable
import androidx.compose.foundation.gestures.rememberDraggableState
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
import androidx.compose.ui.input.nestedscroll.NestedScrollSource
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Velocity
import kotlinx.coroutines.launch

// 定义一个可组合函数,用于展示处理手势滑动的底部表单
@Composable
fun BottomSheetWithSwipeGesture() {
    val sheetState = rememberModalBottomSheetState(
        initialValue = ModalBottomSheetValue.Hidden
    )
    val scope = rememberCoroutineScope()
    var showBottomSheet by remember { mutableStateOf(false) }

    // 创建一个嵌套滚动连接对象,用于处理手势滑动
    val nestedScrollConnection = remember {
        object : NestedScrollConnection {
            override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
                if (source == NestedScrollSource.Drag) {
                    if (available.y > 0 && sheetState.isVisible) {
                        // 向下滑动且底部表单显示时,处理滑动事件
                        scope.launch {
                            sheetState.partialExpand()
                        }
                        return available.copy(x = 0f)
                    }
                }
                return Offset.Zero
            }

            override suspend fun onPreFling(available: Velocity): Velocity {
                if (sheetState.isVisible) {
                    if (available.y > 0) {
                        // 向下滑动且底部表单显示时,处理快速滑动事件
                        scope.launch {
                            sheetState.hide()
                        }
                        return available.copy(x = 0f)
                    }
                }
                return Velocity.Zero
            }
        }
    }

    ModalBottomSheetLayout(
        sheetState = sheetState,
        sheetContent = {
            Column(
                modifier = Modifier
                   .fillMaxWidth()
                   .padding(16.dp)
                   .nestedScroll(nestedScrollConnection) // 应用嵌套滚动连接
                   .draggable(
                        orientation = Orientation.Vertical,
                        state = rememberDraggableState { delta ->
                            // 处理拖动事件
                            scope.launch {
                                sheetState.offset.value = (sheetState.offset.value + delta).coerceIn(
                                    sheetState.minOffset,
                                    sheetState.maxOffset
                                )
                            }
                        }
                    )
            ) {
                Text(text = stringResource(R.string.bottom_sheet_title))
                Button(
                    onClick = {
                        scope.launch { sheetState.hide() }
                    }
                ) {
                    Text(text = stringResource(R.string.close_bottom_sheet))
                }
            }
        }
    ) {
        Column(
            modifier = Modifier
               .fillMaxSize()
               .padding(16.dp)
        ) {
            Button(
                onClick = {
                    showBottomSheet = true
                    scope.launch { sheetState.show() }
                }
            ) {
                Text(text = stringResource(R.string.show_bottom_sheet))
            }
        }
    }
}

// 预览函数,用于在 Android Studio 中预览界面
@Preview(showBackground = true)
@Composable
fun BottomSheetWithSwipeGesturePreview() {
    BottomSheetWithSwipeGesture()
}

5.2 代码解释

  • nestedScrollConnection:创建一个 NestedScrollConnection 对象,用于处理嵌套滚动事件。在 onPreScroll 和 onPreFling 方法中,根据滑动方向和底部表单的状态,处理滑动和快速滑动事件。
  • draggable 修饰符:为底部表单添加 draggable 修饰符,允许用户通过手势拖动底部表单。在 state 参数中,处理拖动事件,更新底部表单的偏移量。

5.3 处理底部表单的选项点击事件

在底部表单中,通常会有一些选项,用户点击这些选项时需要执行相应的操作。以下是一个处理选项点击事件的示例代码:

kotlin

import androidx.compose.foundation.clickable
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.launch

// 定义一个可组合函数,用于展示处理选项点击事件的底部表单
@Composable
fun BottomSheetWithOptionClick() {
    val sheetState = rememberModalBottomSheetState(
        initialValue = ModalBottomSheetValue.Hidden
    )
    val scope = rememberCoroutineScope()
    var showBottomSheet by remember { mutableStateOf(false) }

    ModalBottomSheetLayout(
        sheetState = sheetState,
        sheetContent = {
            Column(
                modifier = Modifier
                   .fillMaxWidth()
                   .padding(16.dp)
            ) {
                Text(
                    text = stringResource(R.string.bottom_sheet_title),
                    style = MaterialTheme.typography.h6
                )
                Divider(
                    modifier = Modifier
                       .fillMaxWidth()
                       .padding(top = 8.dp, bottom = 16.dp)
                )
                // 底部表单的选项列表
                Column {
                    for (i in 1..5) {
                        Text(
                            text = "Option $i",
                            modifier = Modifier
                               .fillMaxWidth()
                               .padding(vertical = 8.dp)
                               .clickable {
                                    // 处理选项点击事件
                                    scope.launch {
                                        sheetState.hide()
                                        // 这里可以添加点击选项后的具体操作
                                        println("Option $i clicked")
                                    }
                                },
                            style = MaterialTheme.typography.body1
                        )
                    }
                }
                Button(
                    onClick = {
                        scope.launch { sheetState.hide() }
                    },
                    modifier = Modifier
                       .fillMaxWidth()
                       .padding(top = 16.dp)
                ) {
                    Text(text = stringResource(R.string.close_bottom_sheet))
                }
            }
        }
    ) {
        Column(
            modifier = Modifier
               .fillMaxSize()
               .padding(16.dp)
        ) {
            Button(
                onClick = {
                    showBottomSheet = true
                    scope.launch { sheetState.show() }
                }
            ) {
                Text(text = stringResource(R.string.show_bottom_sheet))
            }
        }
    }
}

// 预览函数,用于在 Android Studio 中预览界面
@Preview(showBackground = true)
@Composable
fun BottomSheetWithOptionClickPreview() {
    BottomSheetWithOptionClick()
}

5.4 代码解释

  • clickable 修饰符:为每个选项的 Text 组件添加 clickable 修饰符,当用户点击选项时,会执行相应的操作。在这个示例中,点击选项后会隐藏底部表单,并打印出点击的选项信息。

六、底部表单的性能优化

6.1 减少不必要的重绘

在使用底部表单时,要尽量减少不必要的重绘。例如,在底部表单的内容中,如果某些部分不需要频繁更新,可以将其提取到 remember 块中,避免每次重组时都重新计算。以下是一个示例:

kotlin

import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview

// 定义一个可组合函数,用于展示优化重绘的底部表单
@Composable
fun OptimizedBottomSheet() {
    val sheetState = rememberModalBottomSheetState(
        initialValue = ModalBottomSheetValue.Hidden
    )
    val scope = rememberCoroutineScope()
    var showBottomSheet by remember { mutableStateOf(false) }

    // 使用 remember 缓存不需要频繁更新的文本
    val staticText = remember { stringResource(R.string.bottom_sheet_title) }

    ModalBottomSheetLayout(
        sheetState = sheetState,
        sheetContent = {
            Column(
                modifier = Modifier
                   .fillMaxWidth()
                   .padding(16.dp)
            ) {
                Text(text = staticText)
                Button(
                    onClick = {
                        scope.launch { sheetState.hide() }
                    }
                ) {
                    Text(text = stringResource(R.string.close_bottom_sheet))
                }
            }
        }
    ) {
        Column(
            modifier = Modifier
               .fillMaxSize()
               .padding(16.dp)
        ) {
            Button(
                onClick = {
                    showBottomSheet = true
                    scope.launch { sheetState.show() }
                }
            ) {
                Text(text = stringResource(R.string.show_bottom_sheet))
            }
        }
    }
}

// 预览函数,用于在 Android Studio 中预览界面
@Preview(showBackground = true)
@Composable
fun OptimizedBottomSheetPreview() {
    OptimizedBottomSheet()
}

6.2 代码解释

  • remember 函数:用于缓存 staticText,确保在组件重组时不会重新计算该文本。这样可以减少不必要的重绘,提高性能。

6.3 优化布局

在设计底部表单的布局时,要避免嵌套过多的组件,减少布局的复杂度。可以使用 BoxColumn 和 Row 等简单的布局组件来实现所需的布局效果。例如,在前面的定制内容示例中,尽量保持布局的简洁性。

七、底部表单的兼容性问题及解决方案

7.1 不同屏幕尺寸的适配

在不同屏幕尺寸的设备上,底部表单可能会出现显示不全或布局混乱的问题。为了解决这个问题,可以使用 Modifier 的 fillMaxWidth 和 wrapContentHeight 属性,确保底部表单的宽度充满屏幕,高度根据内容自动调整。同时,可以使用 dp 单位来设置组件的尺寸,保证在不同屏幕密度下的显示效果一致。

7.2 代码示例

kotlin

import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview

// 定义一个可组合函数,用于展示适配不同屏幕尺寸的底部表单
@Composable
fun ScreenSizeAdaptiveBottomSheet() {
    val sheetState = rememberModalBottomSheetState(
        initialValue = ModalBottomSheetValue.Hidden
    )
    val scope = rememberCoroutineScope()
    var showBottomSheet by remember { mutableStateOf(false) }

    ModalBottomSheetLayout(
        sheetState = sheetState,
        sheetContent = {
            Column(
                modifier = Modifier
                   .fillMaxWidth() // 宽度充满屏幕
                   .wrapContentHeight() // 高度根据内容自动调整
                   .padding(16.dp)
            ) {
                Text(text = stringResource(R.string.bottom_sheet_title))
                Button(
                    onClick = {
                        scope.launch { sheetState.hide() }
                    }
                ) {
                    Text(text = stringResource(R.string.close_bottom_sheet))
                }
            }
        }
    ) {
        Column(
            modifier = Modifier
               .fillMaxSize()
               .padding(16.dp)
        ) {
            Button(
                onClick = {
                    showBottomSheet = true
                    scope.launch { sheetState.show() }
                }
            ) {
                Text(text = stringResource(R.string.show_bottom_sheet))
            }
        }
    }
}

// 预览函数,用于在 Android Studio 中预览界面
@Preview(showBackground = true)
@Composable
fun ScreenSizeAdaptiveBottomSheetPreview() {
    ScreenSizeAdaptiveBottomSheet()
}

7.3 低版本 Android 系统的兼容性

在低版本的 Android 系统上,可能会出现一些兼容性问题。为了确保底部表单在不同版本的 Android 系统上都能正常显示,可以使用 AndroidX 库,并在 build.gradle 文件中设置合适的 minSdkVersion。同时,要避免使用一些低版本系统不支持的特性和 API。