2007年9月烧毁。 2017年9月,苹果将时尚重新流行,推出了iPhone X.我们的中国朋友毫不犹豫地从苹果复制了这种设计也就不足为奇了(尽管第一个迷你条纹仍然在Essential Phone中,但并没有起飞)。 但是,我们现在看到了什么? 华为P20,华硕Zenfone 5,一加6,摩托罗拉One Power,小米Redmi 6和其他或多或少的知名制造商已经生产或宣布了刘海手机。 三星和谷歌是这场
争夺无框技术的争夺战的最后据点。 还是不行 据传言,谷歌Pixel 3 XL也将
带有优雅的领口。 好吧,作为开发人员,我们只能为此剪裁优化其应用程序,以便用户可以继续舒适地使用它们。 我要求猫下提供详细信息。

首先,我们需要确定应用程序是否需要任何优化?
如果您有一个全屏应用程序或主题中包含
windowActionBarOverlay = true
,则很可能需要它。
几乎所有应用程序都离一个屏幕很远,并且您可能不会注意到其中一个布局的布局。 特别是在应用程序具有大量遗留代码的情况下。 因此,您仍应浏览所有主屏幕并仔细检查。 让我们找出为此需要做的事情。
1.准备测试设备/仿真器
为了使用刘海测试您的应用程序,您需要(谢谢,加油!)AndroidP。当前,Android P Preview 5可用于以下设备(感谢Project Treble):
基本电话
Google Pixel 2;
Google Pixel 2 XL;
Google Pixel
Google Pixel XL
诺基亚7 plus;
一加6;
Oppo R15 Pro;
索尼Xperia XZ2;
体内X21UD;
Vivo X21;
小米Mi Mix 2S。
要在您的设备上安装Android P,只需转到
此处 ,然后为您的设备单击“获取Beta”。 空中飞行或自己滚动-选择是您的。 网站上的说明附后。
但是,如果您不能或不想在设备上安装Android P,则没有人取消模拟器。
此处的设置说明。
2.以编程方式打开爆炸本身(如果没有硬件)
一切都很简单:转到系统->开发人员选项->模拟带有切口的显示。
有3种选项可供选择:

它们看起来如下:
3.浏览主屏幕
当然,每个人的情况都会有所不同。 有人有简单的逻辑,有人没有。 我将给出一些示例,这些示例在我的应用程序中都具有经过布局的屏幕。
探索 | 个人资料 |
---|
 |  |
现在让我们看看消除布局缺陷的方法是什么。
不提高compileSdkVersion
从20 API开始,出现了
WindowInsets类,它是一个
Rect对象,它描述屏幕的可访问部分和不可访问部分。 这些方法与它们一起出现在View中,可用于处理屏幕无法访问部分的坐标:
WindowInsets dispatchApplyWindowInsets(WindowInsets); WindowInsets onApplyWindowInsets(WindowInsets); void requestApplyInsets(); void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener);
有关如何使用它们的详细信息在
这里 。
有两种使用这些方法的方法:
a)在布局或视图的布局中放置标记
android:fitsSystemWindows="true"
;
b)从代码中执行:
layout.setFitsSystemWindows(true); layout.requestApplyInsets();
是 | 已成为 |
---|
 |  |
将compileSdkVersion升级到版本28
在不久的将来,您将不得不切换到该版本,那么为什么不现在就为此做准备呢? 但是要小心,如果您的项目中有单元测试(我希望您有它们),那么JUnit软件包已经移开了。 在此说明如何连接。
那么,Android P现在为我们提供了哪些选择?
答:WindowManager.LayoutParams具有3个新标志:
如何申请?
window.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
B.如果选项A不适合您,并且您需要考虑到不幸的保险开关的位置(例如,状态栏中会显示某些内容,例如Telegram中的连接消息),那么在这种情况下,新的
DisplayCutout类将有所帮助。
考虑其方法:
有了他们,您已经可以做所有想像得到的事情。 是否要-在其代码中移动
margin
。
OnApplyWindowInsetsListener
需要,请在
OnApplyWindowInsetsListener
处理它,并进行
consumeDisplayCutout()
。 也许您需要更复杂的操作。 我将举一个简单的例子来说明爆炸。
class SampleFragment() : Fragment() { private lateinit var root: ViewGroup override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { return inflater.inflate(R.layout.sample_fragment, container, false) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) root = view.findViewById(R.id.root) addArrowsToCutout() } private fun addArrowsToCutout() { // , attach window, null' val cutoutList = root.rootWindowInsets?.displayCutout?.boundingRects cutoutList?.forEach { addArrow(context!!.getDrawable(R.drawable.left), it.left.toFloat(), it.top + (it.bottom - it.top).toFloat() / 2, ::calculateLeftArrow) addArrow(context!!.getDrawable(R.drawable.right), it.right.toFloat(), it.top + (it.bottom - it.top).toFloat() / 2, ::calculateRightArrow) addArrow(context!!.getDrawable(R.drawable.top), it.left + (it.right - it.left).toFloat() / 2, it.top.toFloat(), ::calculateTopArrow) addArrow(context!!.getDrawable(R.drawable.bottom), it.left + (it.right - it.left).toFloat() / 2, it.bottom.toFloat(), ::calculateBottomArrow) } } private fun addArrow(arrowIcon: Drawable, x: Float, y: Float, calculation: (View, Float, Float) -> Unit) { val arrowView = ImageView(context) arrowView.setImageDrawable(arrowIcon) arrowView.layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT) root.addView(arrowView) arrowView.post { calculation(arrowView, x, y) } } private fun calculateLeftArrow(arrowView: View, x: Float, y: Float) { arrowView.x = x - arrowView.width arrowView.y = y - arrowView.height / 2 } private fun calculateRightArrow(arrowView: View, x: Float, y: Float) { arrowView.x = x arrowView.y = y - arrowView.height / 2 } private fun calculateTopArrow(arrowView: View, x: Float, y: Float) { arrowView.x = x - arrowView.width / 2 arrowView.y = y - arrowView.height } private fun calculateBottomArrow(arrowView: View, x: Float, y: Float) { arrowView.x = x - arrowView.width / 2 arrowView.y = y } }
人像
风景
因此,如我们所见,边缘将给我们带来一些不便,并使我们做出额外的手势/额外的操作。 原则上,一切都解决了。 最主要的是要尽快消除布局缺陷,以便有足够的准备时间。 成功处理您的修改。 希望Google不会破坏其Play!