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

Android库Edge-to-Edge适配问题及无依赖解决方案有效性验证

问题:Edge-to-Edge模式下视频控件被遮挡,无AndroidX依赖的适配方案验证

我开发了一个视频播放器库,当前遇到强制Edge-to-Edge模式下的适配问题:视频控件及其他视图被导航栏和应用栏遮挡。我希望在不引入AndroidX传递依赖的前提下解决该问题,设计了仅当Edge-to-Edge生效时,根据系统内边距设置Activity内容视图内边距的方案。以下是我编写的代码,想确认该方案是否能覆盖所有场景或存在潜在问题:

public static void setEdgeToEdgeInsets(View view) {
    Context viewContext = view.getContext();
    if(viewContext instanceof Activity){
        int targetSdk = viewContext.getApplicationInfo().targetSdkVersion;
        if (Build.VERSION.SDK_INT >= 35 && targetSdk>=35) {
            ((Activity)viewContext).getWindow().getDecorView().setOnApplyWindowInsetsListener((v, windowInsets) -> {
                Insets in = windowInsets.getInsets(WindowInsets.Type.systemBars());
                view.setPadding(in.left, in.top, in.right, in.bottom);
                return windowInsets;
            });
        }
    }
}

方案分析与潜在问题

你的适配思路方向正确,但存在场景覆盖不全和逻辑漏洞,具体问题如下:

1. Edge-to-Edge生效判断逻辑片面

仅通过API >=35 + targetSdk >=35判断Edge-to-Edge是否生效并不准确:

  • API 30~34版本已经支持通过Window.setDecorFitsSystemWindows(false)开启Edge-to-Edge模式,你的代码完全遗漏了这些版本的适配
  • 即使在API 35+环境下,开发者也可能通过代码手动关闭Edge-to-Edge模式(比如设置getDecorView().setFitsSystemWindows(true)),此时你的逻辑会错误执行

2. 覆盖DecorView原有监听器风险

直接给DecorView设置OnApplyWindowInsetsListener会覆盖该视图上已存在的监听器,导致其他依赖该监听器的系统逻辑或业务逻辑失效。更合理的做法是给目标view本身绑定监听器,而非DecorView。

3. 未处理视图重置与配置变化

当设备发生横竖屏切换、分屏等配置变化时,视图可能被重新创建,此时之前绑定的监听器会失效,需要在视图重建后重新调用该方法。

4. Padding设置逻辑粗暴

直接用系统内边距替换视图原有padding会丢失视图自身的padding配置,正确的做法应该是叠加系统内边距与原有padding,而非直接覆盖。


优化后的代码示例

public static void setEdgeToEdgeInsets(View view) {
    Context context = view.getContext();
    if (!(context instanceof Activity)) {
        return;
    }
    Activity activity = (Activity) context;
    Window window = activity.getWindow();
    
    // 准确判断当前是否处于Edge-to-Edge模式
    boolean isEdgeToEdgeEnabled = !window.getDecorView().getFitsSystemWindows();
    if (!isEdgeToEdgeEnabled) {
        return;
    }
    
    // 给目标视图绑定监听器,避免干扰DecorView原有逻辑
    view.setOnApplyWindowInsetsListener((v, windowInsets) -> {
        Insets systemInsets;
        // 兼容API 30以下版本(无AndroidX依赖)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            systemInsets = windowInsets.getInsets(WindowInsets.Type.systemBars());
        } else {
            systemInsets = windowInsets.getSystemWindowInsets();
        }
        
        // 叠加原有padding与系统内边距
        int newLeft = v.getPaddingLeft() + systemInsets.left;
        int newTop = v.getPaddingTop() + systemInsets.top;
        int newRight = v.getPaddingRight() + systemInsets.right;
        int newBottom = v.getPaddingBottom() + systemInsets.bottom;
        v.setPadding(newLeft, newTop, newRight, newBottom);
        
        // 传递Insets给子视图,保证嵌套视图的适配逻辑正常执行
        return windowInsets;
    });
    
    // 手动触发一次Insets分发,确保视图初始化阶段就能获取正确内边距
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        view.requestApplyInsets();
    } else {
        // API 23以下版本兼容
        view.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
    }
}

额外注意事项

  • 若视频播放器包含全屏模式,需在全屏状态下清除设置的padding,避免出现多余内边距
  • 对于嵌套滚动视图(如RecyclerView),建议使用android:fitsSystemWindows="true"配合监听器逻辑,避免滚动区域异常

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 15:27:33