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

DrawerLayout与手势冲突时setSystemGestureExclusionRects在Realme机型不生效如何解决

问题原因

  • 最核心的错误是手势排除区域使用了全局屏幕坐标,而非当前View的相对坐标:systemGestureExclusionRects要求传入的Rect坐标是相对于你调用该方法的View自身的左上角,不是全局屏幕坐标。你用屏幕高度计算的区域如果和当前View的实际布局位置不匹配,就会出现识别位置偏移的问题,这也是你修改参数无效、区域跑到左上角的核心原因。
  • 多余的onDraw调用:onDraw是高频触发的绘制生命周期,在这里反复更新排除区域属于冗余操作,还可能导致不必要的重绘。
  • 部分国产ROM(包括Realme UI)对系统手势排除逻辑做了定制修改,原生API的调用逻辑需要配合ROM特性做调整。

修复方案

  1. 修正坐标计算逻辑,改用当前View自身的尺寸计算排除区域,不要使用全局屏幕尺寸:
override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
    super.onLayout(changed, l, t, r, b)
    if (changed) {
        updateGestureExclusion()
    }
}

// 移除onDraw中的updateGestureExclusion调用,不需要在这里触发

private fun updateGestureExclusion() {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
        return
    }
    systemGestureExclusionRects = listOf(createSystemGestureExclusionRect())
}

private fun createSystemGestureExclusionRect(): Rect {
    // 用当前View自身的高度计算,不要用屏幕全局高度
    val viewHeight = height
    val heightInDp = SizeUtils.px2dp(viewHeight.toFloat())
    val excludeWidth = SizeUtils.dp2px(56f)
    return if (heightInDp <= 200) {
        Rect(0, 0, excludeWidth, viewHeight)
    } else {
        val topInDp = (heightInDp - 200) / 2f
        val top = SizeUtils.dp2px(topInDp)
        val bottom = top + SizeUtils.dp2px(200f)
        Rect(0, top, excludeWidth, bottom)
    }
}
  1. 优先用官方内置适配:如果你使用的是AndroidX的DrawerLayout,升级到androidx.drawerlayout:drawerlayout:1.2.0及以上版本,该版本已经内置了系统手势返回的冲突适配,不需要手动编写排除区域代码即可自动处理冲突。
  2. 验证调试:开启开发者选项中的「显示手势排除区域」开关,可直接在屏幕上看到你设置的排除区域的实际位置,快速验证坐标是否正确。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 12:09:03