1. The background

Apple has been leading the design trend, and bangs have been controversial since the release of the iPhone X. But anyway, Android made the splash, but the P briefly added a few cool new features, but the biggest and most intuitive change was to make the switch to something like the Huawei P20’s top-notch screen design, which also landed on the system level.

Many manufacturers are also gradually introducing the bang-screen design of mobile phones, the more common in China are the OPPO R15 and Huawei P20.

1.1. Introduction

The appearance of Bangs screen, I think everybody should have a concept, the way of realizing bangs screen of different manufacturer nevertheless also has not quite, this needs to have a concept first. In terms of the current situation in the market, it can be divided into two categories, one is the standard Android P Api, and the other is the manufacturer in Android P following the system, do special adaptation.

For example, Huawei P20 uses the Android P standard Api, while OPPO R15 has its own adaptation Api.

1.2. Need for adaptation

Android P version provides a unified bang screen scheme and three-way bang screen adaptation scheme:

  • Pages with a status bar are not affected by the bangs feature
  • If a page is displayed in full screen, the system moves the application screen down to avoid the fringe area
  • The full-screen page that has been adapted to Android P application can be used in The Liu Hai area through the adaptation solution provided by Google to truly achieve full-screen display.

2. Build an environment

When there is no corresponding system at hand, emulators are a good way. Recently, Google has also released emulators for Android P. Another way is to find some platforms that support real computer cloud testing, such as Huawei cloud testing platform, which is also a solution, but not as convenient as local simulator.

2.1. Huawei Terminal Open Laboratory

2.2. Local emulators

Choose the emulator of Android P, if you need to update the SDK yourself, just download the update.

The fluted area of the bangs is mostly to make room for cameras and other sensors. For a device or emulator that does not have bangs, you can use the Developer option to Simulate a Display with a Cutout to enable bangs.

The Android P emulator has four fringe modes: None, Narrow Display Cutout, Tall Display Cutout, and Wide Display Cutout. As shown below:

3. Compatibility impact

It is also clear that the cutting area of the bangs screen exists in the status bar, so there is no need for our special treatment on the status bar page, and the system will help us deal with it.

For full-screen pages, separate processing is required. What I’ve done here is I’ve simply made a full-screen page, where each bar is the same width so that you can see the difference in layout.

A full-screen page that does not support a fringe and touches a fringe will cause the UI to sink, and if it is not a list layout, the controls at the bottom will be obscured.

There are some bangs block the effect of the area, in fact, mainly depends on the UI designer to avoid, do not appear in the bangs cutting place, design can operate the area, affect the user operation.

4. Official bangs

Having said that, we still need to adapt bangs in a technological way. Android P bangs have standard APIS for adaptation, while some manufacturers’ own bangs, such as OPPO R15, need to follow its development documents for separate adaptation.

Android P has a dedicated Api to support the latest bangs: DisplayCutout.

4.1. Turn on the bangs

You can enable the function of simulating bang-screen debugging on non-bang-screen P phones

  • In the Developer Options screen, scroll down to the drawing section, and then click the “Simulate a display with a notch” Settings item
  • Select bangs size information

As shown below:

4.2. Bangs

After bangs debug is turned on, browse through all the pages of the app, test for any occlusion problems, or problems caused by scrolling down, and adapt the layout of the pages that have problems. Adaptation schemes are as follows:

The adaptation solution provided by Google can set whether to use the area of the bangs screen in full screen mode.

// Google officially provides the default adaptation screen bangs
val attrib = window.attributes
attrib.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS

Copy the code

New layout attribute layoutInDisplayCutoutMode contains three optional modes, respectively is:

// The window declaration uses the fringe area
public static final int LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS = 1;
// By default, full-screen Windows do not use the bangs. Non-full-screen Windows use the bangs normally
public static final int LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT = 0;
// Declare no bangs
public static final int LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER = 2;
Copy the code

4.3. Height of the bangs

In full-screen mode, our app’s background fills the entire screen, and key information like controls and text is laid out outside the status bar to ensure that key information is not obscured (Google requires that the groove height be the same as the bangs). We need to have a way to obtain the height of the bang screen groove, just can achieve the design and layout of the time, put aside a safe distance.

4.3.1. Interface for obtaining bangs size information

Android P already has a standard Api for measuring the groove of the fringe screen: DisplayCutout.

The fringe recess is right in the middle of the screen, so only the **getSafeInsetTop() method returns the desired result, while the other getSafeInsetXXX()** methods return 0. The code looks like this:

btn_always.postDelayed(Runnable {

    val displayCutout = btn_always.rootWindowInsets.displayCutout
    if (null == displayCutout) {
        Log.e(TAG, "displayCutout is empty")
        return@Runnable
    }
    Log.i(TAG, "SafeInsetBottom:" + displayCutout.safeInsetBottom);
    Log.i(TAG, "SafeInsetLeft:" + displayCutout.safeInsetLeft);
    Log.i(TAG, "SafeInsetRight:" + displayCutout.safeInsetRight);
    Log.i(TAG, "SafeInsetTop:" + displayCutout.safeInsetTop);


}, 100)

Copy the code

The output is:

SafeInsetBottom:0
SafeInsetLeft:0
SafeInsetRight:0
SafeInsetTop:84
Copy the code

4.3.2. Interface for obtaining system status bar height

After obtaining the height of the bangs, we also need to obtain the height of the system status bar, the code is as follows:

fun getStatusBarHeight(context: Context): Int {
    
    var result = 0

    val resourceId = context.resources.getIdentifier("status_bar_height"."dimen"."android")
    if (0 < resourceId) {
        result = context.resources.getDimensionPixelOffset(resourceId)
    }

    return result
}
Copy the code

5. Fringe screen adaptation from other manufacturers

Vendors like Huawei, Oppo, and Vivo didn’t implement the bangs according to Android P standards, either. They modified the bangs themselves. However, they will provide complete adaptation documentation, which requires us to directly read the development documentation they provide for adaptation. The screen adaptation of each manufacturer is as follows:

vendor introduce
huawei https://mini.eastday.com/bdmip/180411011257629.html
Oppo https://open.oppomobile.com/wiki/doc#id=10159
Vivo https://dev.vivo.com.cn/doc/document/info?id=103

5.1. Huawei

Huawei provides the Liu Screen Api, which can be called in reflection mode.

5.1.1. Determine whether the bang-screen interface exists

The code is as follows:

/** * Check whether huawei liuhaiscreen *@paramContext Context object *@returnTrue: Yes Liu Haiping; False: non-bangs */
fun hasNotchInScreen(context: Context): Boolean {
    var ret = false
    try {
        val cl = context.getClassLoader()
        val HwNotchSizeUtil = cl.loadClass("com.huawei.android.util.HwNotchSizeUtil")
        val method = HwNotchSizeUtil.getMethod("hasNotchInScreen")
        ret = method.invoke(HwNotchSizeUtil) as Boolean

    } catch (e: ClassNotFoundException) {
        Log.e(TAG, "hasNotchInScreen ClassNotFoundException")}catch (e: NoSuchMethodException) {
        Log.e(TAG, "hasNotchInScreen NoSuchMethodException")}catch (e: Exception) {
        Log.e(TAG, "hasNotchInScreen Exception")}finally {
        return ret
    }
}

Copy the code

5.1.2. Interface for obtaining bangs size information

The code is as follows:

/** * Obtain the height and width of Huawei bangs *@paramContext Context object *@return[0] is bangs width int; [1] Value is bangs height */
fun getNotchSize(context: Context): IntArray {
    var ret = intArrayOf(0.0)
    try {
        val cl = context.classLoader
        val HwNotchSizeUtil = cl.loadClass("com.huawei.android.util.HwNotchSizeUtil")
        val method = HwNotchSizeUtil.getMethod("getNotchSize")
        ret = method.invoke(HwNotchSizeUtil) as IntArray
    } catch (e: ClassNotFoundException) {
        Log.e(TAG, "getNotchSize ClassNotFoundException")}catch (e: NoSuchMethodException) {
        Log.e(TAG, "getNotchSize NoSuchMethodException")}catch (e: Exception) {
        Log.e(TAG, "getNotchSize Exception")}finally {
        return ret
    }
}

Copy the code

5.1.3. Use bangs for display on the application page

Add Huawei’s new FLAG_NOTCH_SUPPORT mode to Windows as follows:

/** * Set the application window in the digging area of huawei Liu Screen phone *@paramWindow application page Window object */
fun setFullScreenWindowLayoutInDisplayCutout(window: Window?). {

    if (null == window) {
        return
    }

    val layoutParams: WindowManager.LayoutParams = window.attributes

    try {
        val layoutParamsExCls = Class.forName("com.huawei.android.view.LayoutParamsEx")
        val con = layoutParamsExCls.getConstructor(WindowManager.LayoutParams::class.java)
        val layoutParamsExObj = con.newInstance(layoutParams)
        val method = layoutParamsExCls.getMethod("addHwFlags".Int: :class.javaPrimitiveType)
        method.invoke(layoutParamsExObj, FLAG_NOTCH_SUPPORT)
    } catch (e: ClassNotFoundException) {
        Log.e(TAG, "hw notch screen flag api error")}catch (e: NoSuchMethodException) {
        Log.e(TAG, "hw notch screen flag api error")}catch (e: IllegalAccessException) {
        Log.e(TAG, "hw notch screen flag api error")}catch (e: InstantiationException) {
        Log.e(TAG, "hw notch screen flag api error")}catch (e: InvocationTargetException) {
        Log.e(TAG, "hw notch screen flag api error")}catch (e: Exception) {
        Log.e(TAG, "other Exception")}}Copy the code

5.2. Oppo

For Oppo, the height of his bangs is fixed at 80px.

/** * Check whether it is Oppo bangs *@paramContext Context object *@returnTrue: Yes Liu Haiping; False: non-bangs */
fun hasNotchInScreenAtOppo(context: Context): Boolean {
    returncontext.packageManager!! .hasSystemFeature("com.oppo.feature.screen.heteromorphism")}Copy the code

Returns true for bangs, but this method can only identify bangs supported by the Oppo brand.

5.3 in Vivo

In Vivo system, an interface is added to judge whether the device has a groove or not, which can be called by launching. The code looks like this:

/** * Determine whether Voio has grooves **@paramContext Context object *@returnTrue indicates that the feature is present. False indicates that the feature is absent
fun hasNotchInScreenAtVoio(context: Context): Boolean {
    var ret = false
    try {
        val cl = context.classLoader
        val FtFeature = cl.loadClass("android.util.FtFeature")
        val method = FtFeature.getMethod("isFeatureSupport".Int: :class.javaPrimitiveType)
        ret = method.invoke(FtFeature, NOTCH_IN_SCREEN_VOIO) as Boolean

    } catch (e: ClassNotFoundException) {
        Log.e(TAG, "hasNotchInScreen ClassNotFoundException")}catch (e: NoSuchMethodException) {
        Log.e(TAG, "hasNotchInScreen NoSuchMethodException")}catch (e: Exception) {
        Log.e(TAG, "hasNotchInScreen Exception")}finally {
        return ret
    }
}
Copy the code

6. Conclusion

After reading this article, I think you have some understanding of the Android P bangs, but I’m not sure if different manufacturers will tweak it, so if you have any questions, feel free to study them and leave a comment in the comments section.