刘海屏适配

基于安卓9.0对于刘海屏的适配做下简单的总结,当前前提是应用是沉浸式的体验效果,如果无需做到沉浸式的体验效果,则可忽略,因为一般情况下刘海的区域和高度刚好和系统导航栏一样高,可以不考虑刘海,本片主要整理沉浸式体验的刘海屏适配梳理。

1.设置全屏

代码很简单,放在setContentView之前就行,运行后导航栏不显示,然后内容区域也不会到刘海区域,没有刘海的手机默认就到屏幕顶部了,这里的模拟器有刘海。

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //1.设置全屏
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        Window window = getWindow();
        window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
        
        setContentView(R.layout.activity_main);
    }

2.判断手机是否刘海

判断手机是否支出刘海定义到一个方法

    private boolean hasDisplayCutout(Window window) {

        DisplayCutout displayCutout;
        View rootView = window.getDecorView();
        WindowInsets insets = rootView.getRootWindowInsets();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && insets != null){
            displayCutout = insets.getDisplayCutout();
            if (displayCutout != null){
                if (displayCutout.getBoundingRects() != null && displayCutout.getBoundingRects().size() > 0 && displayCutout.getSafeInsetTop() > 0){
                    return true;
                }
            }
        }
        return false; //模拟器可能会出现异常,真机不会
    }

3.设置是否让内容区域延伸进刘海及是否设置成沉浸式

对于刘海屏我们将内容延伸进刘海区域,并且设置成沉浸式

//3.设置是否让内容区域延伸进刘海及是否设置成沉浸式
        if (isDisplayCutout){//让内容区域延伸进刘海

            WindowManager.LayoutParams params = window.getAttributes();
            /**
             *  * @see #LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT 全屏模式,内容下移,非全屏不受影响
             *  * @see #LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES 允许内容去延伸进刘海区
             *  * @see #LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER 不允许内容延伸进刘海区
             */
            params.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
            window.setAttributes(params);

            //设置成沉浸式
            int flags = View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
            int visibility = window.getDecorView().getSystemUiVisibility();
            visibility |= flags; //追加沉浸式设置
            window.getDecorView().setSystemUiVisibility(visibility);
        }

至此刘海屏的适配就完成了,内容已经延伸到了刘海里面。

4.设置控件是否避开刘海区域

适配完成之后,如果我们有一个控件在顶部的时候可能会出现尴尬的被刘海切掉。

因此需要对控件是否避开刘海区域做规避,一般情况下刘海的高度就是状态栏的高度,我们简单处理的话可以按照状态栏的高度去处理,追求极致的话可以看看每一家手机厂商官网的sdk介绍,然后区分厂商适配。原则就是我们判断下,如果是刘海屏,对控件设置一个向上的margin值或者对其父控件设置一个paddingTop的值,这个值就是刘海的高度。

获取刘海的高度:

    public int heightForDisplayCutout(){
        int resID = getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resID > 0){
            return getResources().getDimensionPixelSize(resID);
        }
        return 96;
    }

对控件设置margin值,感兴趣的也可以对其父控件设置padding值,这里就不做演示了:

        View view = findViewById(R.id.view);
        RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) view.getLayoutParams();
        params.topMargin = heightForDisplayCutout();
        view.setLayoutParams(params);

至此整个刘海屏适配完成。附上完整代码

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //1.设置全屏
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        Window window = getWindow();
        window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);

        //2.判断手机是否刘海
        boolean isDisplayCutout = isDisplayCutout(window);

        //3.设置是否让内容区域延伸进刘海及是否设置成沉浸式
        if (isDisplayCutout) {//让内容区域延伸进刘海

            WindowManager.LayoutParams params = window.getAttributes();
            /**
             *  * @see #LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT 全屏模式,内容下移,非全屏不受影响
             *  * @see #LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES 允许内容去延伸进刘海区
             *  * @see #LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER 不允许内容延伸进刘海区
             */
            params.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
            window.setAttributes(params);

            //设置成沉浸式
            int flags = View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
            int visibility = window.getDecorView().getSystemUiVisibility();
            visibility |= flags; //追加沉浸式设置
            window.getDecorView().setSystemUiVisibility(visibility);
        }

        setContentView(R.layout.activity_main);

        View view = findViewById(R.id.view);
        RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) view.getLayoutParams();
        params.topMargin = heightForDisplayCutout();
        view.setLayoutParams(params);

    }

    private boolean isDisplayCutout(Window window) {
        DisplayCutout displayCutout;
        View rootView = window.getDecorView();
        WindowInsets insets = rootView.getRootWindowInsets();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && insets != null) {
            displayCutout = insets.getDisplayCutout();
            if (displayCutout != null) {
                if (displayCutout.getBoundingRects() != null && displayCutout.getBoundingRects().size() > 0 && displayCutout.getSafeInsetTop() > 0) {
                    return true;
                }
            }
        }
        return false; //模拟器可能获取失败,模拟器演示时将此处改为true看效果
    }


    //通常情况下,刘海的高就是状态栏的高
    public int heightForDisplayCutout() {
        int resID = getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resID > 0) {
            return getResources().getDimensionPixelSize(resID);
        }
        return 96;
    }

}

Demo地址:https://github.com/987570437/DisplayCutoutDemo

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值