Get the height of "notch" so contents won't be cut off

6.1k views Asked by At

How can I get the height of recent android phones' notch, preferably in pixels?

I have an implementation where an image MUST be at the top in full screen.

With the addition of a notch to recently released phones, this image will be cut out by the notch. My idea is to get the notch height and add a margin above it dynamically to accommodate different notch sizes.

Any help or other approaches would be greatly appreciated.

3

There are 3 answers

0
aspix On

The easiest way to get the cutout's height in pixels is to override onAttachedToWindow() function of your View. View being attached to window is the main requirement to rootWindowInsets being non-null. Note that it's safe to check SDK version, because complete support of cutout has been started since Android Pie.

override fun onAttachedToWindow() {
     super.onAttachedToWindow()
     layoutParams = LayoutParams(MATCH_PARENT, WRAP_CONTENT).apply {
           topMargin = 
               if (SDK_INT >= Build.VERSION_CODES.P) rootWindowInsets?.displayCutout?.safeInsetTop ?: 0 
               else 0 
     }

}

In case that your View isn't CustomView you should add OnAttachStateChangeListener:

imageView.addOnAttachStateChangeListener(object : View.OnAttachStateChangeListener {
     override fun onViewDetachedFromWindow(v: View?) { }

     override fun onViewAttachedToWindow(v: View?) {
         // call the code from above starting from 'layoutParams = ...' on your View object
     }
})

Don't forget to change LayoutParams(MATCH_PARENT, WRAP_CONTENT) for your own needs.

0
Zain On

Starting from Android Q (API level 29), you'd use the windowInsets to get the cutout/notch height using the below activity extension function:

@RequiresApi(Build.VERSION_CODES.Q)
fun Activity.getNotchHeight(): Int? =
    if (SDK_INT >= Build.VERSION_CODES.R)
        windowManager.currentWindowMetrics.windowInsets
            .displayCutout?.safeInsetTop
    else
        windowManager.defaultDisplay.cutout?.safeInsetTop
0
ChinLoong On

I used the method below(in Kotlin):

*It will only work in Android P and above.

*My activity is a full screen activity.

*My assumption is android phone with notches are relatively new will either come out of the box with Android P or have been rapidly updated to Android P.

Create a OnGlobalLayoutListener

private val onDisplayCutoutReadyListener : ViewTreeObserver.OnGlobalLayoutListener = ViewTreeObserver.OnGlobalLayoutListener{
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {

        var displayCutout = window.decorView.rootWindowInsets.displayCutout
        if (displayCutout.boundingRects.size>0) {
            val notchRect = displayCutout.boundingRects.get(0)
            Log.v(TAG,"notch height in pixels="+notchRect.height())
        }
    }

}

Add the listener to your activity's rootview using .viewTreeObserver.addOnGlobalLayoutListener()

layout_fullscreen.viewTreeObserver.addOnGlobalLayoutListener(onDisplayCutoutReadyListener)

My layout xml where layout_fullscreen is the rootview.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layout_fullscreen"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<RelativeLayout
    android:layout_width="match_parent"
    android:layout_weight="1"
    android:layout_height="0dp">
    <com.baidu.mapapi.map.MapView
        android:id="@+id/map_location"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</RelativeLayout>