简介
Android V 上默认会使用全面屏兼容方式,影响应用显示,导致应用内跟导航标题重合,无法点击上移的内容。
默认情况下,如果应用以 Android 15(API 级别 35)为目标平台,在搭载 Android 15 的设备上,应用默认采用全屏。
解决方案
先说适配方案,后面有官方文档的介绍说明变更内容、应用自查方法和配置建议。
方法:实现无边框应用。
如何检查应用尚未实现无边框
如果您的应用还没有全面屏,那么您很可能会受到影响。除了针对已经采用无边框的应用的情况之外,您还应考虑以下事项:
- 如果您的应用在 Compose 中使用 Material 3 组件 (androidx.compose.material3)(例如
TopAppBar
、BottomAppBar
和NavigationBar
),这些组件可能不会受到影响,因为它们会自动处理边衬区。- 如果您的应用在 Compose 中使用 Material 2 组件 (androidx.compose.material),这些组件不会自动处理边衬区。不过,您可以访问边衬区,并手动应用边衬区。在 androidx.compose.material 1.6.0 及更高版本中,使用
windowInsets
参数为 BottomAppBar、TopAppBar、BottomNavigation 和 NavigationRail 手动应用边衬区。同样,对 Scaffold 使用contentWindowInsets
参数。- 如果您的应用使用视图和 Material 组件 (com.google.android.material),则大多数基于视图的 Material 组件(例如
BottomNavigationView
、BottomAppBar
、NavigationRailView
或NavigationView
)均可处理边衬区,无需执行额外的操作。不过,如果使用AppBarLayout
,则需要添加android:fitsSystemWindows="true"
。- 对于自定义可组合项,请手动将边衬区作为内边距应用。如果您的内容在
Scaffold
内,您可以使用 Scaffold 内边距值使用边衬区。否则,请使用某个 WindowInsets 应用内边距。- 如果您的应用使用视图和
BottomSheet
、SideSheet
或自定义容器,请使用 ViewCompat.setOnApplyWindowInsetsListener 应用内边距。对于RecyclerView
,请使用此监听器应用内边距,并添加clipToPadding="false"
。
(一)针对传统的Java传统视图参考方案(无Compose使用)
【Java】创建界面时,设置属性 fitsSystemWindows属性为 true
如果做成插件化,没有使用Activity布局可配置,如PreferenceScreen中没有android:fitsSystemWindows="true"配置,且设置activitybase.xml线性布局此属性也无法解决,可选择在onCreateView生命周期中渲染界面。
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
<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
。
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全面屏导致的负面影响:
全屏强制应用
2、当API和系统都是Android 15时,会受到全面屏负面影响,导致top Bar和导航栏异常重合问题。
由于 Android 15 全屏强制措施,现在许多元素被状态栏、“三按钮”导航栏或刘海屏隐藏。隐藏界面包括 Material 2 顶部应用栏、悬浮操作按钮和列表项。
无边框应用
3、在 Android 15 设备上采用无边框应用,并应用边衬区以便不隐藏界面。
如需了解应用边衬区的其他注意事项,请参阅无边框视图和无边框 Compose 指南。
配置说明
如果您的应用以 Android 15 或更高版本为目标平台,Configuration
将不再排除系统栏。如果您在 Configuration
类中使用屏幕尺寸计算布局,则应根据需要将其替换为合适的 ViewGroup
、WindowInsets
或 WindowMetricsCalculator
等更好的替代方案。
从 API 1 开始,Configuration
一直可用。它通常从 Activity.onConfigurationChanged
获取。它可提供窗口密度、方向和大小等信息。从 Configuration
返回的窗口大小的一个重要特征是它之前排除了系统栏。
配置大小通常用于资源选择(如 /res/layout-h500dp
),这仍然是一个有效的用例。不过,我们一直不建议将其用于布局计算。如果这样做,您应该立即离开。您应该根据自己的使用场景,将 Configuration
替换为更合适的代码。
如果您使用其计算布局,请使用适当的 ViewGroup
,例如 CoordinatorLayout
或 ConstraintLayout
。如果您使用它来确定系统导航栏的高度,请使用 WindowInsets
。如果您想知道应用窗口的当前大小,请使用 computeCurrentWindowMetrics
。
以下列表介绍了受此更改影响的字段:
- Configuration.screenWidthDp 和 screenHeightDp 尺寸不再排除系统栏。
- Configuration.smallestScreenWidthDp 会受到
screenWidthDp
和screenHeightDp
更改的间接影响。 - 在近方形设备上,对
screenWidthDp
和screenHeightDp
的更改会间接影响 Configuration.orientation。 - Display.getSize(Point) 会受到
Configuration
中变更的间接影响。从 API 级别 30 开始,此 API 已被废弃。 - 从 API 级别 33 开始,
Display.getMetrics()
就一直以这种方式运行。