You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android中无法获取Insets求助:如何获取摄像头刘海的Insets值?

解决刘海区域Insets获取问题的方案

一、通过WindowInsetsCompat监听系统Insets回调

首先确保Activity已开启全屏布局,取消系统自动布局适配:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    // 开启全屏,让布局延伸到刘海区域
    window.setDecorFitsSystemWindows(false)
    window.insetsController?.apply {
        systemBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
        hide(WindowInsetsCompat.Type.systemBars())
    }

    // 监听WindowInsets变化,获取DisplayCutout值
    ViewCompat.setOnApplyWindowInsetsListener(findViewById(android.R.id.content)) { _, insets ->
        val cutoutInsets = insets.getInsets(WindowInsetsCompat.Type.displayCutout())
        // 此处即可取到日志中的88px左侧刘海偏移量
        Log.d("CutoutInfo", "Left: ${cutoutInsets.left}, Top: ${cutoutInsets.top}")
        insets
    }
}

关键:必须设置window.setDecorFitsSystemWindows(false),否则系统会自动将布局限制在安全区域,导致Insets被消费无法获取真实值。

二、Jetpack Compose中获取DisplayCutout

使用Compose内置的Insets API,结合状态监听:

@Composable
fun FullScreenDrawing() {
    // 开启Edge-to-Edge模式,让布局延伸到系统栏/刘海区域
    enableEdgeToEdge()

    val windowInsets = rememberWindowInsets(WindowInsetsCompat.Type.displayCutout())
    val cutoutInsets = remember {
        derivedStateOf {
            windowInsets.getInsets(LocalWindow.current)
        }
    }

    // 监听Insets变化
    LaunchedEffect(cutoutInsets.value) {
        Log.d("ComposeCutout", "Left Offset: ${cutoutInsets.value.left}")
    }

    Box(modifier = Modifier.fillMaxSize()) {
        // 绘制Bitmap时,用cutoutInsets.value.left调整偏移量
        Canvas(modifier = Modifier.fillMaxSize()) {
            drawBitmap(
                bitmap = yourBitmap,
                topLeft = Offset(cutoutInsets.value.left.toFloat(), 0f)
            )
        }
    }
}

注意:需依赖最新版androidx.compose.foundation:foundation库,确保Insets API兼容性。

三、兜底:监听配置变化广播

若上述方法仍无法捕获,可通过系统广播监听配置变更,重新获取Insets:

private val configChangeReceiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
        if (intent?.action == Intent.ACTION_CONFIGURATION_CHANGED) {
            val insets = WindowInsetsCompat.toWindowInsetsCompat(window.decorView.rootWindowInsets)
            val cutoutInsets = insets.getInsets(WindowInsetsCompat.Type.displayCutout())
            Log.d("CutoutOnConfig", "Left: ${cutoutInsets.left}")
        }
    }
}

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    registerReceiver(configChangeReceiver, IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED))
}

override fun onDestroy() {
    super.onDestroy()
    unregisterReceiver(configChangeReceiver)
}

该方法可应对部分机型刘海动态显示/隐藏的场景。

内容的提问来源于stack exchange,提问作者confused

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 01:42:40