借助Android 9(API级别28),Google正式开始支持著名的缺口,即顶部的切口显示(因为最近两年是缺口的年份?)。 我不能断言,但是有了缺口的支持,大多数品牌都推出了他们的镂空显示器版本,因此,作为开发人员,我们需要考虑另一种优势,特别是如果我们正在使用沉浸式体验。
为了让您稍微了解一下我所研究的内容,在处理该缺口时,我注意到的是设备的缺口要么是状态栏的大小,要么是垂直调整状态栏的长度。 因此,由于状态栏从技术上讲并不是您应用程序的一部分,因此Android几乎总是会处理它。
但..
当您要隐藏状态栏以使全屏视图时会发生什么? 这是您作为开发人员需要解决的问题。
并且由于上周我已经花了很多时间解决它,所以我认为它是让您大家节省时间的完美的新教程。
让我们开始吧。
先决条件☝️
在本教程中,我使用了Android Studio 4.0 Preview,但其他AS版本也应该可以使用。
项目设置⚙️
首先是第一件事。 我们需要解决这个问题。 为了禁止状态栏沉浸在应用程序中。 请执行下列操作:
1.打开一个新项目。
2.选择一个空的活动项目模板。 这将创建一个带有操作栏的空白屏幕。
3.输入项目的任何名称,然后从语言中选择Kotlin
4.单击完成。
5.运行项目以查看初始应用程序的外观。
物质依赖😍
由于我们需要对应用程序进行一些样式设置,因此我们需要Android的Material库,该库目前不在应用程序中,因此第一件事是将Material库添加到我们的项目中。 为此:
- 打开build.gradle (模块)
- 在依赖项部分添加以下行:
implementation'com.google.android.material:material:1.1.0'
注意:在撰写本文时,最新的Material版本是1.1.0,但是您可以使用所需的Google Maven存储库或MVN存储库中的任何最新稳定版本。
3.同步项目。
添加自定义工具栏
您必须考虑是否已经设置了工具栏,为什么还要添加另一个。 这是因为项目设置的默认工具栏来自我们无法控制的父级布局,因此当在应用程序上启用全屏显示时,工具栏会与其他系统元素一起隐藏,但我们希望拥有控制权为了不自动隐藏它。 设置方法如下:
1.打开styles.xml。
2.将您的父主题从Theme.AppCompat.Light.DarkActionBar替换为Theme.MaterialComponents.NoActionBar.Bridge (在此阶段运行应用程序不应显示任何工具栏) 。
3.打开activity_main.xml。
4.添加以下行代替占位符TextView以添加工具栏(在此阶段运行应用程序应显示一个空的工具栏) 。
< androidx.appcompat.widget.Toolbar
android:id = "@+id/toolbar"
android:minHeight = "?attr/actionBarSize"
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
android:background = "?attr/colorPrimary"
app:layout_constraintTop_toTopOf = "parent"
app:layout_constraintStart_toStartOf = "parent"
app:layout_constraintEnd_toEndOf = "parent" />
5.打开MainActivity.kt。
6.在setContentView()之后添加此行,以设置我们自己的工具栏并显示应用程序标题。
setSupportActionBar(findViewById(R.id.toolbar))
启用全屏🌅
要启用全屏,我们需要隐藏顶部的状态栏和底部的系统导航栏,为此,Android开发人员指南为其提供了正确的文档: https : //developer.android.com/training/system-ui/沉浸式 :
1.打开styles.xml 。
2.在AppTheme下添加新样式:
< style name = "AppTheme.Fullscreen" parent = "AppTheme" >
< item name = "android:windowFullscreen" > true </ item >
< item name = "android:windowLayoutInDisplayCutoutMode" tools:targetApi = "p" > shortEdges </ item >
</ style >
3.打开AndroidManifest.xml
4.在MainActivity属性中,添加具有刚刚创建的样式的android:theme属性:
< activity
android:name = ".MainActivity"
android:theme = "@style/AppTheme.Fullscreen" >
< intent-filter >
< action android:name = "android.intent.action.MAIN" />
< category android:name = "android.intent.category.LAUNCHER" />
</ intent-filter >
</ activity >
5.现在在您的MainActivity.kt中 ,添加以下行:
override fun onWindowFocusChanged (hasFocus: Boolean ) {
super .onWindowFocusChanged(hasFocus)
if (hasFocus) {
hideSystemUIAndNavigation( this )
}
}
private fun hideSystemUIAndNavigation (activity: Activity ) {
val decorView: View = activity.window.decorView
decorView.systemUiVisibility =
(View.SYSTEM_UI_FLAG_IMMERSIVE
// Set the content to appear under the system bars so that the
// content doesn't resize when the system bars hide and show.
or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN // Hide the nav bar and status bar
or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_FULLSCREEN)
}
6.运行应用程序,一切顺利!
除了你不是。
如果您此时在带有槽口/切口显示的设备上运行该应用程序,您会注意到该槽口隐藏了工具栏:
这就是这个故事的全部问题。
修复🔧
方法一:
为了解决issum,您可能会想到的第一种方法是简单地在工具栏上添加填充以将其放置在槽口下方。 但是,由于我们在不同的设备上具有不同的高度,因此我们无法对恒定值(例如24dp或48dp)进行硬编码,以便在工具栏顶部添加边距。
但是,您必须考虑系统必须设置状态栏的高度。 是的,有,您可以通过@android:dimen / status_bar_height访问它,但是由于这是一个私有值,因此将android:layout_marginTop =” @ android:dimen / status_bar_height”添加到工具栏 引发构建错误:
AAPT: error: resource android:dimen/status_bar_height is private.
即使您确实添加了一个恒定值,它也可能适用于槽口但不适用于无槽口设备:
方法二和法宝:🎩
解决该问题的方法是简单地以编程方式对其进行处理:仅在需要时添加填充。 而且由于Google有一些新的API可以解决这个问题,因此实现这种破解非常容易:
1.在您的MainActivity.kt中 ,添加一个新方法:
@SuppressLint( "NewApi" )
private fun adjustToolbarMarginForNotch () {
// Notch is only supported by >= Android 9
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
val windowInsets = window.decorView.rootWindowInsets
if (windowInsets != null ) {
val displayCutout = windowInsets.displayCutout
if (displayCutout != null ) {
val safeInsetTop = displayCutout.safeInsetTop
val newLayoutParams = toolbar.layoutParams as ViewGroup.MarginLayoutParams
newLayoutParams.setMargins( 0 , safeInsetTop, 0 , 0 )
toolbar.layoutParams = newLayoutParams
}
}
}
}
2.在onWindowFocusChanged中的hideSystemUIAndNavigation(this)的正下方调用此方法,以使更改在隐藏系统UI时生效 。
注意:由于我们在此处调用的某些方法是Google API的新功能(例如rootViewInsets,displayCutout等),因此它们仅受Android 9支持。并且由于notch在设备中是一种新趋势,所有带有缺口的新设备都可以运行Android≥9,因此我们在这里都不错。 👌
如果现在运行该应用程序,您会看到只有在我们有一个缺口时才添加边距:
额外:造型🎨
到目前为止,我们只需要在空白区域添加一些样式或将工具栏扩展到顶部,以使其看起来不太奇怪即可。 为此:
1.在您的activity_main.xml中 ,在工具栏顶部添加一个具有工具栏大小(?attr / actionBarSize)的新视图,例如:
< View
android:layout_width = "match_parent"
android:layout_height = "?attr/actionBarSize"
android:background = "?attr/colorPrimary"
app:layout_constraintTop_toTopOf = "parent"
app:layout_constraintStart_toStartOf = "parent"
app:layout_constraintEnd_toEndOf = "parent" />
2.运行该应用程序以查看更改。
因此,您可以使用视图的背景和/或工具栏来根据自己的喜好调整样式:
编码愉快! 💻
最终版本的源代码
与往常一样,请让我知道我的教程是否对您有任何帮助,以及我可以通过发送DM或Tweet来撰写教程的内容而有所改进: twitter.com/waseefakhtar✌️
先前发布在https://proandroiddev.com/android-material-toolbar-vs-displaycutout-6ae99b2b7ef0
翻译自: https://hackernoon.com/android-material-component-toolbar-vs-displaycutout-7hbk3yt7