Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
4.1k views
in Technique[技术] by (71.8m points)

android - Is there any way to stretch layout when device has cutout (notch)?

I'm making my project able to handle notch/cutout because users can see big black rectangle area when in landscape mode. Since my app's layout will be safe after stretching, I decided to make layout fit width including notch's width too.

When I used short edge mode, app's screen itself seemed to stretch, but layout view (like RelativeLayout or ConstraintLayout, etc) doesn't follow window's width.

enter image description here

I can be sure that window is stretched because black rectangle now became white rectangle which is same color with window's default background color of my app.

I tested 2 ways to perform stretching

1. Adding android:windowLayoutInDisplayCutoutMode to style.xml

<style name="AppTheme.night" parent="Theme.AppCompat.Light.NoActionBar">
    <!-- Customize your theme here. -->
    <item name="android:windowLayoutInDisplayCutoutMode" tools:targetApi="o_mr1">shortEdges</item>
    <item name="colorPrimary">@color/colorPrimaryN</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDarkN</item>
    <item name="colorAccent">@color/colorAccentN</item>
    ...
</style>

I don't know if targetApi tag might make things not working, but this made app show white rectangle, but didn't make layout view stretched

2. Setting short edge mode programatically

val att = window.attributes
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
    att.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
}

It seemed I could set short edge mode programatically in my activity class, so I tried with this code above, but the result was same as first way. I even tried to move these lines before calling setContentView, and after calling setContentView, but result was still same.

I tried to set full screen mode to with code below, but result was like this image

@Suppress("DEPRECATION")
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
    val controller = window.insetsController

    if(controller != null) {
        controller.hide(WindowInsets.Type.statusBars() or WindowInsets.Type.navigationBars())
        controller.systemBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
    }
} else {
    window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN)
}

enter image description here

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="?attr/backgroundPrimary"
    tools:context=".CheckUpdateScreen">

    <ProgressBar
        android:id="@+id/prog"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:layout_alignParentTop="false"
        android:layout_alignParentEnd="true"
        android:layout_alignParentBottom="false"
        android:layout_centerVertical="true"
        android:layout_marginStart="24dp"
        android:layout_marginEnd="24dp" />

    <TextView
        android:id="@+id/status"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/prog"
        android:layout_alignStart="@+id/prog"
        android:layout_alignBottom="@+id/retry"
        android:layout_marginStart="0dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="0dp"
        android:layout_marginBottom="0dp"
        android:layout_toStartOf="@+id/retry"
        android:gravity="center_vertical"
        android:text="@string/down_state_rea"
        android:textColor="?attr/TextPrimary"
        android:textSize="18sp" />

    <Button
        android:id="@+id/retry"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/prog"
        android:layout_alignEnd="@+id/prog"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="0dp"
        android:backgroundTint="?attr/ButtonPrimary"
        android:text="@string/down_redown"
        android:textAllCaps="false"
        android:textColor="?attr/TextPrimary" />

</RelativeLayout>

This is my screen's layout xml file (Picture above)

I may be misunderstanding something because it's first time to handle notch/cutout thing. Is it normal that I can't stretch layout view even though I set short edge mode? Or are there any special layout views which can handle notch/cutout stretching?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

According to the official documentation:

Android might not allow the content view to overlap the system bars. To override this behavior and force content to extend into the cutout area, apply any of the following flags to the view visibility via the View.setSystemUiVisibility(int) method:

  • SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
  • SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
  • SYSTEM_UI_FLAG_LAYOUT_STABLE

Also note that setSystemUiVisibility is deprecated in API Level 30 and windowInsetsController can be used instead.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...