1.compose中怎么使用对话框?
2.怎么显示Popup弹窗?
一、Compose显示对话框
二、Popup
Popup就类似以前的Popupwindow,我们可以看到其实上面的DropdownMenu是Popup的一个具体实现。
2.1 Popup定义
Popup的定义如下:
@Composable
fun Popup(alignment: Alignment = Alignment.TopStart,offset: IntOffset = IntOffset(0, 0),onDismissRequest: (() -> Unit)? = null,properties: PopupProperties = PopupProperties(),content: @Composable () -> Unit
) {val popupPositioner = remember(alignment, offset) {AlignmentOffsetPositionProvider(alignment,offset)}Popup(popupPositionProvider = popupPositioner,onDismissRequest = onDismissRequest,properties = properties,content = content)
}
相关属性分析
属性 | 取值 | 备注 |
alignment | 在父控件的对齐方式。 TopStart:顶部开头对齐 TopCenter:顶部居中对齐 | 对齐方式。 |
offset | offset 偏移。IntOffset(x,y) x是水平方向上的偏移,y是竖直方向上的偏移 | 偏移量。相对于对齐位置的基准线。 |
onDismissRequest | 这个相当于原来的Popup设置outsideClick处理 | 当用户在弹出窗口外单击时执行的回调 |
properties | PopupProperties对象。 | 弹窗属性 |
content | 包裹的Compose控件 | 子控件卡槽。(弹窗内容区域) |
2.2 测试样例
例如下面的弹窗,点击按钮,弹出一个Popup。
2.2.1 Activity页面
class PopupActivity : ComponentActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)enableEdgeToEdge()setContent {ComposeAnimTheme {Scaffold(modifier = Modifier.fillMaxSize().statusBarsPadding()) { innerPadding ->// 测试弹窗popupTest()}}}}
}
popUp Test为弹窗组件。
弹窗含有一个列表,列表中有三个菜单项。
/*** Popup弹窗测试** @author zhouronghua* @time 2024/10/12 17:27*/
@Preview
@Composable
fun popupTest() {// 是否显示弹窗状态val expandState = remember {mutableStateOf(false)}Column() {Button(onClick = {expandState.value = true}) {Text(text = "打开 Popup")}if (expandState.value) {// 列表显示数据val items = mutableListOf<Pair<ImageVector, String>>(Icons.Filled.Favorite to "收藏",Icons.Filled.Edit to "编辑",Icons.Filled.Delete to "删除")// 弹窗Popup(alignment = Alignment.TopStart,onDismissRequest = {Log.e("xxx", "执行了onDismissRequest")expandState.value = false},offset = IntOffset(10, 140),) {Column(modifier = Modifier.width(IntrinsicSize.Min)// 添加阴影部分.shadow(elevation = 2.dp, shape = RoundedCornerShape(3.dp)).background(Color.White, shape = RoundedCornerShape(3.dp))) {// 根据列表数据构建列表想items.forEachIndexed { index, item ->// 子项dropdownMenuItem(expandState, item.first, item.second)}}}}}
}
Compose的弹窗思路与View系统实现思想有一些区别:
1)View的实现类似于多窗口的方式,底层一个页面,Popup作为一层窗口来显示。show显示,dismiss隐藏/关闭。
2)Compose是可组合方式,在同一个窗口层次,通过状态控制弹窗组件是否显示来实现。
2.2.2 Popup组件
popupTest为弹窗组件,定制弹窗内容。
/*** Popup弹窗测试** @author zhouronghua* @time 2024/10/12 17:27*/
@Preview
@Composable
fun popupTest() {// 是否显示弹窗状态val expandState = remember {mutableStateOf(false)}Column() {Button(onClick = {expandState.value = true}) {Text(text = "打开 Popup")}if (expandState.value) {// 列表显示数据val items = mutableListOf<Pair<ImageVector, String>>(Icons.Filled.Favorite to "收藏",Icons.Filled.Edit to "编辑",Icons.Filled.Delete to "删除")// 弹窗Popup(alignment = Alignment.TopStart,onDismissRequest = {Log.e("xxx", "执行了onDismissRequest")expandState.value = false},offset = IntOffset(10, 140),) {Column(modifier = Modifier.width(IntrinsicSize.Min)// 添加阴影部分.shadow(elevation = 2.dp, shape = RoundedCornerShape(3.dp)).background(Color.White, shape = RoundedCornerShape(3.dp))) {// 根据列表数据构建列表想items.forEachIndexed { index, item ->// 子项dropdownMenuItem(expandState, item.first, item.second)}}}}}
}
1)因为列表想仅有三项,可以使用Column,不需要考虑列表滚动效果。
2)Modifier.shadow定义组件的阴影效果。elevation定义阴影区域的大小,shape:阴影区域的形状。
3) items.forEachIndexed根据列表数据生成列表项控件。dropdownMenuItem是子项的可组合控件。
2.2.3 菜单子项
菜单子项是一个Row,包含一个Icon和一个Text。
/*** 弹窗列表子项** @author zhouronghua* @time 2024/10/12 17:26*/
@Composable
fun dropdownMenuItem(state: MutableState<Boolean>, icon: ImageVector, text: String) {val interactionSource = remember { MutableInteractionSource() }// 按下状态val pressState = interactionSource.collectIsPressedAsState()// 获取焦点状态val focusState = interactionSource.collectIsFocusedAsState()DropdownMenuItem(text = {Row(horizontalArrangement = Arrangement.spacedBy(10.dp)) {Icon(imageVector = icon,contentDescription = text,tint = if (pressState.value || focusState.value) Color.Blue else Color.Black)Text(text = text,color = if (pressState.value || focusState.value) Color.Blue else Color.Black)}},onClick = {state.value = false},enabled = true,interactionSource = interactionSource,)
}
1) DropdownMenuItem是Material 的下拉菜单控件,text是可组合控件,定义菜单项内容;
@Composable
fun DropdownMenuItem(text: @Composable () -> Unit,onClick: () -> Unit,modifier: Modifier = Modifier,leadingIcon: @Composable (() -> Unit)? = null,trailingIcon: @Composable (() -> Unit)? = null,enabled: Boolean = true,colors: MenuItemColors = MenuDefaults.itemColors(),contentPadding: PaddingValues = MenuDefaults.DropdownMenuItemContentPadding,interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
) {DropdownMenuItemContent(text = text,onClick = onClick,modifier = modifier,leadingIcon = leadingIcon,trailingIcon = trailingIcon,enabled = enabled,colors = colors,contentPadding = contentPadding,interactionSource = interactionSource,)
}
属性 | 取值 | 备注 |
text | 定义菜单项内容区的可组合组件 | text是可组合控件,定义菜单项内容 |
onClick | 菜单项点击事件处理。 | 定义菜单项点击事件处理; |
enabled | 菜单项是否可用。布尔值 | |
leadingIcon | 起始位置的Icon | 可组合控件 |
trailingIcon | 尾部的Icon | 可组合控件 |
colors | MenuItemColors对象。定义内容的字体颜色和图标的字体颜色。 | |
contentPadding | 内容区的内边距 | |
interactionSource | interactionSource-可变交互源,表示此菜单项的交互流。您可以创建并传入自己记住的实例来观察交互,并在不同状态下自定义此菜单项的外观/行为。 | 通俗的话来说就是定义按下,弹起,焦点状态的效果。 |
实例中很清晰的展示了获取这些交互状态的方法。
// 交互状态来源val interactionSource = remember { MutableInteractionSource() }// 按下状态val pressState = interactionSource.collectIsPressedAsState()// 获取焦点状态val focusState = interactionSource.collectIsFocusedAsState()
如图,标题栏的盘点按钮,点击以后,开始显示一个Popup弹窗。
1)通过一个状态State控制是否显示和隐藏Popup
2) 定义弹窗的位置和内容。