You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Android Compose Material3下拉菜单在Android 16横屏模式下对齐异常问题咨询

Android Compose Material3下拉菜单在Android 16横屏模式下对齐异常问题咨询

你好呀,我最近折腾Compose Material3时碰到了一个奇怪的布局问题,试了好几种方法都没搞定,想请教下大家这是实验性Material3特性的bug,还是我代码里有没注意到的问题?

问题具体表现

  • 竖屏模式:不管是Android 15还是16,App里的所有功能都正常,右上角的下拉菜单能和触发它的MoreVert按钮完美对齐
  • 横屏模式:Android 15依然一切正常,但Android 16里的下拉菜单居然和按钮错位了,位置明显偏移,完全不符合预期

我写的完整代码如下

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.safeDrawingPadding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults.topAppBarColors
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
import com.github.zardozz.material3scafold.ui.theme.Material3ScafoldTheme

class MainActivity : ComponentActivity() {
    @OptIn(ExperimentalMaterial3Api::class)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContent {
            Material3ScafoldTheme {
                Scaffold(modifier = Modifier.safeDrawingPadding(),
                    topBar = {
                        TopAppBar(
                            colors = topAppBarColors(
                                containerColor = MaterialTheme.colorScheme.primary,
                                titleContentColor = MaterialTheme.colorScheme.onSecondary,
                            ),
                            title = {
                                Text("Top app bar")
                            },
                            actions = {
                                ActionDropdownMenu()
                            },
                        )
                    },
                ) { innerPadding ->
                    Greeting(
                        name = "Android",
                        modifier = Modifier.padding(innerPadding)
                    )
                }
            }
        }
    }
}

@Composable
fun ActionDropdownMenu() {
    var expanded by remember { mutableStateOf(false) }
    IconButton(onClick = { expanded = !expanded }) {
        Icon(Icons.Filled.MoreVert,
            contentDescription = "More options",
            tint = Color.White)
    }
    DropdownMenu(
        expanded = expanded,
        onDismissRequest = { expanded = false }
    ) {
        DropdownMenuItem(
            text = { Text("Option 1") },
            onClick = { /* Do something... */ }
        )
        DropdownMenuItem(
            text = { Text("Option 2") },
            onClick = { /* Do something... */ }
        )
    }
}

@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
    Text(
        text = "Hello $name!",
        modifier = modifier
    )
}

@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
    Material3ScafoldTheme {
        Greeting("Android")
    }
}

我自己的一些排查思路

我自己琢磨了下,觉得可能的方向有这几个:

  • 会不会是ExperimentalMaterial3Api的兼容性问题?毕竟用的是实验性API,在Android 16(API 36)这种新版本系统上可能存在适配漏洞
  • 有没有可能是EdgeToEdge布局的影响?我开了enableEdgeToEdge(),会不会横屏时系统的insets计算在Android 16里有变化,导致DropdownMenu的定位出错?
  • 是不是DropdownMenu的默认定位逻辑在新系统下失效了?默认它应该基于触发的IconButton定位,但横屏Android 16里可能计算锚点位置时出了问题

尝试过的临时方案(没彻底解决)

我试着给DropdownMenu加了个Modifier.offset(x = (-20).dp)手动调整位置,虽然能暂时对齐,但感觉这不是长久之计,不同设备的偏移量可能还不一样。

有没有大佬遇到过类似问题呀?或者能帮我看看代码里有没有哪里写得不对的地方?麻烦啦🥺

火山引擎 最新活动