Android 15 应用适配默认全屏的行为变更(Android V的新特性)

简介

Android V 上默认会使用全面屏兼容方式,影响应用显示,导致应用内跟导航标题重合,无法点击上移的内容。

默认情况下,如果应用以 Android 15(API 级别 35)为目标平台,在搭载 Android 15 的设备上,应用默认采用全屏。

解决方案

先说适配方案,后面有官方文档的介绍说明变更内容、应用自查方法和配置建议。

方法:实现无边框应用。

如何检查应用尚未实现无边框

如果您的应用还没有全面屏,那么您很可能会受到影响。除了针对已经采用无边框的应用的情况之外,您还应考虑以下事项:

  • 如果您的应用在 Compose 中使用 Material 3 组件 (androidx.compose.material3)(例如 TopAppBarBottomAppBarNavigationBar),这些组件可能不会受到影响,因为它们会自动处理边衬区。
  • 如果您的应用在 Compose 中使用 Material 2 组件 (androidx.compose.material),这些组件不会自动处理边衬区。不过,您可以访问边衬区,并手动应用边衬区。在 androidx.compose.material 1.6.0 及更高版本中,使用 windowInsets 参数为 BottomAppBarTopAppBarBottomNavigationNavigationRail 手动应用边衬区。同样,对 Scaffold 使用 contentWindowInsets 参数。
  • 如果您的应用使用视图和 Material 组件 (com.google.android.material),则大多数基于视图的 Material 组件(例如 BottomNavigationViewBottomAppBarNavigationRailViewNavigationView)均可处理边衬区,无需执行额外的操作。不过,++如果使用 AppBarLayout,则需要添加 android:fitsSystemWindows="true"。++
  • 对于自定义可组合项,请手动将边衬区作为内边距应用。如果您的内容在 Scaffold 内,您可以使用 Scaffold 内边距值使用边衬区。否则,请使用某个 WindowInsets 应用内边距。
  • 如果您的应用使用视图和 BottomSheetSideSheet 或自定义容器,请使用 ViewCompat.setOnApplyWindowInsetsListener 应用内边距。对于 RecyclerView,请使用此监听器应用内边距,并添加 clipToPadding="false"

(一)针对传统的Java传统视图参考方案(无Compose使用)

【Java】创建界面时,设置属性 fitsSystemWindows属性为 true

如果做成插件化,没有使用Activity布局可配置,如PreferenceScreen中没有android:fitsSystemWindows="true"配置,且设置activitybase.xml线性布局此属性也无法解决,可选择在onCreateView生命周期中渲染界面。

java 复制代码
public class MainPref extends PreferenceFragmentBase
        implements Preference.OnPreferenceChangeListener {

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View rootView = super.onCreateView(inflater, container, savedInstanceState);
        Log.d(TAG, "onCreateView: rootView = "+ rootView + ", setFitsSystemWindows=true.");
        if (rootView != null) {
            rootView.setFitsSystemWindows(true);
        }
        return rootView;
    }

Note:在一个包含 Fragment 的 Activity 中,onCreate()方法会先被调用,然后再调用 Fragment 的onCreateView()方法。

(二)针对Compose的方案:

1、在build.gradle 添加编译依赖

dependencies {
    implementation "androidx.core:core-ktx:1.6.0" // 当前释放最新应该是1.6.0,可以需修改成以后更新版本
    implementation "androidx.appcompat:appcompat:1.3.1"
    implementation "androidx.constraintlayout:constraintlayout:2.0.4"
}

2、【XML】修改manifest配置布局 fitsSystemWindows属性为 true

XML 复制代码
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    android:id="@+id/main_layout"
    tools:context=".MainActivity">
</androidx.constraintlayout.widget.ConstraintLayout>

3、【Java】修改Activity创建逻辑

默认情况下,每个 ComposeView 都会使用 WindowInsetsCompat 级别使用的所有边衬区。如需更改此默认行为,请将 ComposeView.consumeWindowInsets 设置为 false

Kotlin 复制代码
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    //拿到自定义id的布局进行操作
    ConstraintLayout mainLayout = findViewById(R.id.main_layout);

    ViewCompat.setOnApplyWindowInsetsListener(mainLayout, (v, windowInsets) -> {
        WindowInsetsCompat insetsCompat = ViewCompat.getRootWindowInsets(v);
        if (insetsCompat != null) {
            Insets insets = insetsCompat.getInsets(WindowInsetsCompat.Type.systemBars());
            Log.d(TAG, "left = " + insets.left + ", top = " + insets.top + 
                ", right = " + insets.right + ", bottom = " + insets.bottom);

            v.setPadding(insets.left, insets.top, insets.right, insets.bottom);
        } else {
            Log.d(TAG, "insetsCompat is null");
        }

        // 获取 WindowInsetsControllerCompat 实例
        WindowInsetsControllerCompat windowInsetsController = ViewCompat.getWindowInsetsController(v);

        if (windowInsetsController != null) {
            // 设置状态栏图标和文字为深色
            windowInsetsController.setAppearanceLightStatusBars(true);
        }

        // Return CONSUMED if you don't want want the window insets to keep passing
        // down to descendant views.
        return WindowInsetsCompat.CONSUMED;
    });
}

官方文档

1、变更说明:行为变更:以 Android 15 或更高版本为目标平台的应用 | Android Developers

2、全面屏&无边框应用自检步骤:检查应用是否已采用全屏的检查步骤 | Android Developers

3、配置建议:稳定配置 | Android Developers (google.cn)

UI案例

1、在Android 14的设备上,如果应用没有升级API版本则不会出现Android 15 SDK全面屏导致的负面影响:
以 Android 14 为目标平台且在 Android 15 设备上非全屏的应用

全屏强制应用

2、当API和系统都是Android 15时,会受到全面屏负面影响,导致top Bar和导航栏异常重合问题。

由于 Android 15 全屏强制措施,现在许多元素被状态栏、"三按钮"导航栏或刘海屏隐藏。隐藏界面包括 Material 2 顶部应用栏、悬浮操作按钮和列表项。
以 Android 15(API 级别 35)为目标平台且在 Android 15 设备上为全屏的应用

无边框应用

3、在 Android 15 设备上采用无边框应用,并应用边衬区以便不隐藏界面。
以 Android 15(API 级别 35)为目标平台的应用,在 Android 15 设备上采用无边框应用

如需了解应用边衬区的其他注意事项,请参阅无边框视图无边框 Compose 指南。

配置说明

如果您的应用以 Android 15 或更高版本为目标平台,Configuration 将不再排除系统栏。如果您在 Configuration 类中使用屏幕尺寸计算布局,则应根据需要将其替换为合适的 ViewGroupWindowInsetsWindowMetricsCalculator 等更好的替代方案。

从 API 1 开始,Configuration 一直可用。它通常从 Activity.onConfigurationChanged 获取。它可提供窗口密度、方向和大小等信息。从 Configuration 返回的窗口大小的一个重要特征是它之前排除了系统栏。

配置大小通常用于资源选择(如 /res/layout-h500dp),这仍然是一个有效的用例。不过,我们一直不建议将其用于布局计算。如果这样做,您应该立即离开。您应该根据自己的使用场景,将 Configuration 替换为更合适的代码。

如果您使用其计算布局,请使用适当的 ViewGroup,例如 CoordinatorLayoutConstraintLayout。如果您使用它来确定系统导航栏的高度,请使用 WindowInsets。如果您想知道应用窗口的当前大小,请使用 computeCurrentWindowMetrics

以下列表介绍了受此更改影响的字段:

相关推荐
芋芋qwq4 小时前
Unity UI射线检测 道具拖拽
ui·unity·游戏引擎
长亭外的少年4 小时前
Kotlin 编译失败问题及解决方案:从守护进程到 Gradle 配置
android·开发语言·kotlin
鸿蒙自习室5 小时前
鸿蒙多线程开发——线程间数据通信对象02
ui·harmonyos·鸿蒙
建群新人小猿6 小时前
会员等级经验问题
android·开发语言·前端·javascript·php
大霞上仙7 小时前
element ui table 每行不同状态
vue.js·ui·elementui
1024小神8 小时前
tauri2.0版本开发苹果ios和安卓android应用,环境搭建和最后编译为apk
android·ios·tauri
兰琛8 小时前
20241121 android中树结构列表(使用recyclerView实现)
android·gitee
Y多了个想法8 小时前
RK3568 android11 适配敦泰触摸屏 FocalTech-ft5526
android·rk3568·触摸屏·tp·敦泰·focaltech·ft5526
NotesChapter9 小时前
Android吸顶效果,并有着ViewPager左右切换
android
_祝你今天愉快11 小时前
分析android :The binary version of its metadata is 1.8.0, expected version is 1.5.
android