Dropwmenu 下拉菜单
下拉菜单的行为类似于弹出窗口,并将使用父布局的位置来定位自己在屏幕上的位置。通常,下拉菜单将被放置在一个具有兄弟框的框中,该框将被用作“锚”。请注意,DropdownMenu本身不会占用布局中的任何空间,因为菜单显示在一个单独的窗口中,位于其他内容的顶部。
DropdownMenu的内容通常是DropdownMenuItems,以及自定义内容。使用DropdownMenuItems将产生一个与菜单材质规范匹配的菜单。还要注意,内容被放置在一个可滚动的Column中,因此不支持使用LazyColumn作为内容中的根布局。
当菜单应该关闭时,on遣散请求将被调用——例如,当有一个菜单外的点击,或者当返回键被按下。
下拉菜单根据可用空间改变其位置,始终试图完全可见。根据布局方向,它将尝试水平扩展到其父元素的末尾,然后扩展到其父元素的开始,然后扩展到屏幕末端对齐。在垂直方向上,它将尝试扩展到其父元素的底部,然后从其父元素的顶部扩展到屏幕顶部对齐。当父菜单的布局边界与其视觉边界不一致时,可以提供一个偏移量来调整菜单的位置。注意,偏移量将应用于菜单决定展开的方向。
@Suppress("ModifierParameter")
@Composable
fun DropdownMenu(
expanded: Boolean,
onDismissRequest: () -> Unit,
modifier: Modifier = Modifier,
offset: DpOffset = DpOffset(0.dp, 0.dp),
properties: PopupProperties = PopupProperties(focusable = true),
content: @Composable ColumnScope.() -> Unit
){
val expandedStates = remember { MutableTransitionState(false) }
expandedStates.targetState = expanded
if (expandedStates.currentState || expandedStates.targetState) {
val transformOriginState = remember { mutableStateOf(TransformOrigin.Center) }
val density = LocalDensity.current
val popupPositionProvider = DropdownMenuPositionProvider(
offset,
density
) { parentBounds, menuBounds ->
transformOriginState.value = calculateTransformOrigin(parentBounds, menuBounds)
}
Popup(
onDismissRequest = onDismissRequest,
popupPositionProvider = popupPositionProvider,
properties = properties
) {
DropdownMenuContent(
expandedStates = expandedStates,
transformOriginState = transformOriginState,
modifier = modifier,
content = content
)
}
}
}
NameDescriptionexpanded菜单是否展开onDismissRequest当用户请求取消菜单时调用,例如在菜单边界外点击offset偏移量
Dialog对话框
打开具有给定内容的对话框。
只要对话框是复合层次结构的一部分,它就是可见的。为了让用户取消对话框,onCloseRequest的实现应该包含一个方法来删除从组合层次结构中删除对话框。
@Composable
fun Dialog(
onDismissRequest: () -> Unit,
properties: DialogProperties = DialogProperties(),
content: @Composable () -> Unit
)
onCloseRequest 当用户试图取消对话框时执行。
properties 进一步配置定制对话框的动画,点击边界关闭,后退关闭等等
content 要在对话框中显示的内容
核心代码如下
通过expanded 状态开启下拉菜单,onDismissRequest 在试图关闭的时候修改状态进行关闭,然后selectedIndex 进行开启对话框等等
TopAppBar(
colors = TopAppBarDefaults.topAppBarColors(
containerColor = MaterialTheme.colorScheme.primaryContainer,
titleContentColor = MaterialTheme.colorScheme.primary,
),
title = {
Row {
Row {
Button(
onClick = { settingDrawerState = DrawerState(DrawerValue.Open) },
modifier = Modifier.size(40.dp),
shape = RoundedCornerShape(50),
contentPadding = PaddingCommon.ZERO_PADDING,
colors = ButtonDefaults.buttonColors(Color.White)
) {
Surface(
shape = CircleShape,
border = BorderStroke(0.dp, Color.Gray)
) {
Image(
painter = painterResource(id = R.drawable.test),
contentDescription = null,
modifier = Modifier.size(40.dp),
contentScale = ContentScale.Crop
)
}
}
TextButton(
onClick = { /*TODO*/ },
contentPadding = PaddingCommon.ZERO_PADDING,
) {
Text(text = "白")
}
}
Row(
horizontalArrangement = Arrangement.End,
modifier = Modifier.fillMaxWidth()
) {
Column {
IconButton(onClick = { expanded = true }) {
Icon(
modifier = Modifier
.padding(0.dp)
.fillMaxSize(),
imageVector = Icons.Filled.Add,
contentDescription = "Localized description"
)
}
DropdownMenu(
expanded = expanded,
onDismissRequest = { expanded = false }) {
items.forEachIndexed { index, label ->
DropdownMenuItem(text = {
Text(text = label)
}, onClick = {
selectedIndex = index
expanded = false
})
}
}
}
if (selectedIndex == 1) {
DialogImageAdd(onDismissRequest = {
selectedIndex = 0
})
}
}
}
}
)
@Composable
fun DialogImageAdd(
onDismissRequest: () -> Unit,
properties: DialogProperties = DialogProperties(),
) =
Dialog(onDismissRequest = onDismissRequest, properties = properties) {
var text by rememberSaveable { mutableStateOf("") }
Box(
modifier = Modifier
.background(Color.White)
.padding(10.dp)
) {
Column() {
Row(horizontalArrangement = Arrangement.Center) {
Text(text = "创建文件夹")
}
Row() {
OutlinedTextField(value = text, onValueChange = { text = it }, label = {
Text(text = "名称")
})
}
Button(onClick = {
val file = File("./images/${text}")
if (!file.exists()) {
file.mkdir()
}
}) {
Text(text = "确定")
}
}
}
}