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
相关产品推荐
相关产品推荐

