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

如何解决Android10+游戏中全屏禁用返回滑动手势的问题?

解决Android 10+全屏禁用导航返回滑动手势的问题

我来帮你搞定这个困扰——你遇到的两个坑我之前做游戏时也踩过,咱们一步步拆解问题,再给出靠谱的解决方案。

先说说你之前方案失效的原因

  • 方案1崩溃:在onCreate里直接调用setSystemGestureExclusionRects,此时你的View还没被添加到窗口层级里,系统要求必须在View附加到窗口后才能设置手势排除区域,所以抛出了IllegalStateException: view not added的错误。
  • 方案2只屏蔽下半部分getWindowVisibleDisplayFrame(visibleRect)返回的是应用窗口的可见区域,这个区域会被状态栏(顶部)、导航栏(底部)这类系统UI裁剪,导致你设置的排除Rect只覆盖了屏幕下半段,自然没法全屏禁用手势。

正确的全屏禁用方案

要实现全屏范围内完全屏蔽返回滑动手势,需要满足两个核心要求:

  1. 必须在View完全附加到窗口并完成布局后再设置排除区域;
  2. 构造覆盖整个屏幕的Rect,而非依赖被系统UI裁剪的区域。

修改后的代码示例

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    game = new Lockjaw(this);
    AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
    RelativeLayout layout = new RelativeLayout(this);
    layout.setFitsSystemWindows(true);
    View view = initializeForView(game, config);
    layout.addView(view);
    setContentView(layout);

    // 用View.post()确保View已经完成布局并附加到窗口
    view.post(() -> {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            // 获取当前屏幕的真实尺寸
            DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
            int screenWidth = displayMetrics.widthPixels;
            int screenHeight = displayMetrics.heightPixels;
            
            List<Rect> exclusionRects = new ArrayList<>();
            // 构造覆盖全屏的Rect
            exclusionRects.add(new Rect(0, 0, screenWidth, screenHeight));
            
            getWindow().setSystemGestureExclusionRects(exclusionRects);
        }
    });
}

额外优化:适配屏幕旋转

如果你的游戏支持横竖屏切换,别忘了在配置变化时重新设置排除区域(旋转后屏幕尺寸改变,旧的Rect会失效):

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    // 获取根布局下的游戏View
    View gameView = findViewById(android.R.id.content).getChildAt(0);
    if (gameView != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
        gameView.post(() -> {
            DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
            int screenWidth = displayMetrics.widthPixels;
            int screenHeight = displayMetrics.heightPixels;
            List<Rect> exclusionRects = new ArrayList<>();
            exclusionRects.add(new Rect(0, 0, screenWidth, screenHeight));
            getWindow().setSystemGestureExclusionRects(exclusionRects);
        });
    }
}

关键细节解释

  • View.post()的作用:这个方法会把任务放到View的消息队列中,等到View完成布局、成功附加到窗口后再执行,完美避开了方案1的崩溃问题。
  • 用屏幕尺寸构造Rect:直接通过DisplayMetrics获取屏幕的真实宽高,构造的Rect能覆盖整个显示区域,不会被系统栏裁剪,确保全屏禁用手势。
  • 配置变化重设:屏幕旋转后屏幕尺寸改变,之前设置的排除Rect就不再适配新的屏幕,所以必须重新计算并设置。

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

火山引擎 最新活动