9.0适配刘海屏

刘海屏适配,就是不让刘海遮挡住应用程序,不影响应用程序的正常使用。

竖屏情况下,系统会根据刘海的高度,响应调整状态栏的高度。因此,刘海对竖屏模式没有影响。

可是横屏模式下,刘海区域就会变成一条大黑边。
9.0适配刘海屏_第1张图片Android 9.0系统中提供了3种layoutInDisplayCutoutMode属性来允许应用自主决定该如何对刘海屏设备进行适配:

  • ①LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT:默认的属性,应用程序的内容在竖屏模式下自动延伸到刘海区域,横屏模式下不会延伸到刘海区域。

  • ②LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES:不管横屏还是竖屏模式,都允许应用程序的内容延伸到刘海区域。

  • ③LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER:永远不允许应用程序的内容延伸到刘海区域。

这种情况下,就需要指定layoutInDisplayCutoutMode属性的值,让我们的应用程序具备更好的用户体验。

layoutInDisplayCutoutMode属性可以在xml中指定,创建values-v28文件夹,创建styles.xml文件:

<style name="ActivityTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="android:windowLayoutInDisplayCutoutMode">
        shortEdges <!-- 可选项 default, shortEdges, never -->
    </item>
</style>

layoutInDisplayCutoutMode属性也可以在代码中指定:

if (Build.VERSION.SDK_INT >= 28) {
    WindowManager.LayoutParams params = getWindow().getAttributes();
    params.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
    getWindow().setAttributes(params);
}

9.0适配刘海屏_第2张图片那么问题来了,假如有一个Button正好位于刘海屏的位置,那么就得在设计上进行适配了。
竖屏模式下,顶部View被刘海屏遮挡:
横屏模式下,侧边View也会被遮挡:
Android在9.0系统提供了一套获取安全显示区域的API,只需确认哪些位置有可能被遮挡,并相应的对遮挡位置进行偏移即可:

if (Build.VERSION.SDK_INT >= 28) {
    rootLayout.setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() {
        @Override
        public WindowInsets onApplyWindowInsets(View view, WindowInsets windowInsets) {
            DisplayCutout displayCutout = windowInsets.getDisplayCutout();
            if (displayCutout != null) {
                int left = displayCutout.getSafeInsetLeft();
                int top = displayCutout.getSafeInsetTop();
                int right = displayCutout.getSafeInsetRight();
                int bottom = displayCutout.getSafeInsetBottom();
            }
            return windowInsets.consumeSystemWindowInsets();
        }
    });
}

通过Android9.0提供的获取安全显示区域的API,计算出左上右下的安全距离,再对目标View设置margin间距:


可以看出,我们的控件已经根据计算出的安全距离进行了适当的位置偏移。同时需要注意一点,横屏时,侧边View进行了安全偏移,但是顶部View并未显示在正中。因为DisplayCount让我们所有的View都进行了安全偏移。针对这种“BUG”,只能加判断逻辑,被遮挡的View再去安全偏移,不受影响的View不用管了。

完整代码如下:
activity_cutout.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/rootLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/husky"
    tools:context=".cutout.CutoutActivity">
    <Button
        android:id="@+id/top"
        android:text="顶部可交互控件"
        android:layout_gravity="center_horizontal"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

    <Button
        android:id="@+id/side"
        android:text="侧边可交互控件"
        android:layout_gravity="center_vertical"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
</FrameLayout>

CutoutActivity.java

import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.DisplayCutout;
import android.view.View;
import android.view.WindowInsets;
import android.widget.Button;
import android.widget.FrameLayout;

import com.example.husky.xiangxue.R;

/**
 * 刘海屏适配
 */
public class CutoutActivity extends AppCompatActivity {

    protected Button mTop;
    protected Button mSide;
    protected FrameLayout mRootLayout;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        super.setContentView(R.layout.activity_cutout);
        initView();
    }

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        if (hasFocus && Build.VERSION.SDK_INT >= 19) {
            View decorView = getWindow().getDecorView();
            int option = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                    | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                    | View.SYSTEM_UI_FLAG_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
            decorView.setSystemUiVisibility(option);
        }
    }

    private void initView() {
        mTop = (Button) findViewById(R.id.top);
        mSide = (Button) findViewById(R.id.side);
        mRootLayout = (FrameLayout) findViewById(R.id.rootLayout);

        if (Build.VERSION.SDK_INT>=28){
            mRootLayout.setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() {
                @Override
                public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
                    DisplayCutout displayCutout = insets.getDisplayCutout();
                    if (displayCutout!=null){
                        //获取四周的安全距离
                        int left = displayCutout.getSafeInsetLeft();
                        int top = displayCutout.getSafeInsetTop();
                        int right = displayCutout.getSafeInsetRight();
                        int bottom = displayCutout.getSafeInsetBottom();

                        //设置间距
                        FrameLayout.LayoutParams topLayoutParams = (FrameLayout.LayoutParams) mTop.getLayoutParams();
                        topLayoutParams.setMargins(left,top,right,bottom);
                        FrameLayout.LayoutParams sideLayoutParams = (FrameLayout.LayoutParams) mSide.getLayoutParams();
                        sideLayoutParams.setMargins(left,top,right,bottom);
                    }
                    return insets.consumeSystemWindowInsets();
                }
            });
        }
    }
}

清单文件

<activity android:name=".cutout.CutoutActivity"
                  android:screenOrientation="landscape"
            android:theme="@style/CutoutTheme">
        </activity>

v28/styles.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="CutoutTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <item name="android:windowLayoutInDisplayCutoutMode">
            shortEdges
        </item>
    </style>
</resources>

感谢郭婶:https://blog.csdn.net/guolin_blog/article/details/103112795

你可能感兴趣的:(屏幕适配系列,android)