在Jetpack Compose中如何自定义DropdownMenu的弹出位置?
你之前设置alignment、arrangement不生效的原因是:DropdownMenu属于弹出层类组件,不会继承父布局的排列对齐规则,它的位置默认仅由锚定的父组件位置和自身的offset参数控制。
以下是两种需求的实现方案:
1. 点击位置直接弹出菜单
通过手势监听获取点击坐标,再传入DropdownMenu的offset参数即可实现,修改后的代码如下:
import androidx.compose.foundation.gestures.detectTapGestures import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.* import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.Offset import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.unit.DpOffset import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Window fun main() = Window { var helloText by remember { mutableStateOf("") } Column( modifier = Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ) { Item("Darian", "Russ") { helloText = it } Item("Maynerd", "Andre") { helloText = it } Item("Sandra", "Victoria") { helloText = it } Spacer(modifier = Modifier.height(2.dp)) Text(text = helloText) } } @Composable fun Item(text: String, text2: String, onMenuTab: (String) -> Unit) { var expanded by remember { mutableStateOf(false) } // 存储点击位置的坐标 var touchOffset by remember { mutableStateOf(Offset.Zero) } val density = LocalDensity.current Column( modifier = Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ) { // 替换clickable为手势监听,获取点击坐标 val modifier = Modifier.pointerInput(Unit) { detectTapGestures { offset -> touchOffset = offset expanded = true } } DropdownMenu( expanded = expanded, onDismissRequest = { expanded = false }, // 把像素坐标转为dp,设置弹出偏移 offset = DpOffset( x = with(density) { touchOffset.x.toDp() }, y = with(density) { touchOffset.y.toDp() } ), // 可选:给菜单加圆角更美观 shape = RoundedCornerShape(8.dp) ) { DropdownMenuItem(onClick = { onMenuTab("hello $text $text2") expanded = false }) { Text("Hello") } DropdownMenuItem(onClick = { /* Handle settings! */ }) { Text("Settings") } Divider() DropdownMenuItem(onClick = { /* Handle send feedback! */ }) { Text("Send Feedback") } } Text(text = text, modifier = modifier) Text(text = text2, modifier = modifier) Divider(modifier = Modifier.height(2.dp)) Spacer(modifier = Modifier.height(2.dp)) } }
2. DropdownMenu 居中显示
如果不需要跟随点击位置,只需要固定居中弹出,直接调整offset参数即可实现,以全局水平居中为例:
// 在DropdownMenu所在的Composable中获取屏幕宽度 val screenWidth = LocalConfiguration.current.screenWidthDp.dp // 假设菜单宽度为200.dp,可根据实际情况调整 val menuWidth = 200.dp DropdownMenu( expanded = expanded, onDismissRequest = { expanded = false }, offset = DpOffset( x = (screenWidth - menuWidth) / 2, y = 200.dp // 垂直位置可自行调整 ) ) { // 菜单项内容 }

内容的提问来源于stack exchange,提问作者Mehranjp73
相关产品推荐
相关产品推荐

