android 刘海适配

最近公司项目设计到了刘海适配问题,对于这刘海也是醉了,看了官网和别人的博客才有些了解!
现在对于刘海适配最全面的也就华为了,写的很详细,对于vivo和oppo鄙视一下,写了文档就给个判断是否为刘海的方法,其余就是些废话了。

项目主要每个页面都有一个title,类似首页、视频,正好这俩字被刘海遮住了,没办法,只能适配了。

华为:

    /**
     * 判断华为手机是否为刘海屏
     *
     * @param context
     * @return  true为刘海屏,false非刘海屏
     */
 public static boolean hasNotchInScreen(Context context) {

        boolean ret = false;

        try {

            ClassLoader cl = context.getClassLoader();

            Class HwNotchSizeUtil = cl.loadClass("com.huawei.android.util.HwNotchSizeUtil");

            Method get = HwNotchSizeUtil.getMethod("hasNotchInScreen");

            ret = (boolean) get.invoke(HwNotchSizeUtil);

        } catch (ClassNotFoundException e) {

        } catch (NoSuchMethodException e) {

        } catch (Exception e) {

        } finally {

            return ret;

        }

    }

/**
     * 获取华为手机参数  
     *
     * @param context
     * @return  int[0]值为刘海宽度 int[1]值为刘海高度
     */
    public static int[] getNotchSize(Context context) {

        int[] ret = new int[]{0, 0};

        try {

            ClassLoader cl = context.getClassLoader();

            Class HwNotchSizeUtil = cl.loadClass("com.huawei.android.util.HwNotchSizeUtil");

            Method get = HwNotchSizeUtil.getMethod("getNotchSize");

            ret = (int[]) get.invoke(HwNotchSizeUtil);

        } catch (ClassNotFoundException e) {

        } catch (NoSuchMethodException e) {

        } catch (Exception e) {

        } finally {

            return ret;

        }

    }

/**
     * 设置应用窗口在华为刘海屏手机使用刘海区
     *
     * @param window 应用页面window对象
     */
    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    public static void setFullScreenWindowLayoutInDisplayCutout(Window window) {
        if (window == null) {
            return;
        }
        WindowManager.LayoutParams layoutParams = window.getAttributes();
        try {
            Class layoutParamsExCls = Class.forName("com.huawei.android.view.LayoutParamsEx");
            Constructor con = layoutParamsExCls.getConstructor(WindowManager.LayoutParams.class);
            Object layoutParamsExObj = con.newInstance(layoutParams);
            Method method = layoutParamsExCls.getMethod("addHwFlags", int.class);
            method.invoke(layoutParamsExObj, FLAG_NOTCH_SUPPORT);
        } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) {
        } catch (Exception e) {
        }
    }

oppo ,就给了一个方法,也不知道刘海的高度是多少,只能根据个人判断了

    /**
     * oppo判断是否为刘海屏
     */

    public static boolean hasNotchInOppo(Context context){
        return context.getPackageManager().hasSystemFeature("com.oppo.feature.screen.heteromorphism");
    }

vivo, 和oppo一样差不多

/**
     * vivo 判断是否为刘海屏
     */

    public static final int NOTCH_IN_SCREEN_VOIO = 0x00000020;//是否有凹槽
    public static final int ROUNDED_IN_SCREEN_VOIO = 0x00000008;//是否有圆角

    public static boolean hasNotchInScreenAtVoio(Context context) {
        boolean ret = false;
        try {
            ClassLoader cl = context.getClassLoader();
            Class FtFeature = cl.loadClass("com.util.FtFeature");
            Method get = FtFeature.getMethod("isFeatureSupport", int.class);
            ret = (boolean) get.invoke(FtFeature, NOTCH_IN_SCREEN_VOIO);

        } catch (ClassNotFoundException e) {
        } catch (NoSuchMethodException e) {
        } catch (Exception e) {
        } finally {
            return ret;
        }
    }

看他们各个文档,以及google文档,刘海高度<=状态栏高度的
因为项目每个页面都有title,所以我直接在基类里设置的,通过公用的一个include引用

BaseActivity设置

   @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(getLayoutId());
        //禁止横屏
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        //include里面的title
        TextView empty= (TextView) findViewById(R.id.empty);
      /**
         * 华为下移title位置
         */
        boolean isHWphone = PhoneStyle.hasNotchInScreen(this);
        if (isHWphone) {//true为刘海屏,false则执行布局默认的布局了,
            int[] notchSize = PhoneStyle.getNotchSize(this);
            LinearLayout.LayoutParams layout = (LinearLayout.LayoutParams) empty.getLayoutParams();
            //title下移到刘海下面,log输出notchSize[1]高度为90,但是感觉下移的太多了,所以减了50px
            layout.setMargins(0, notchSize[1] - 50, 0, 0);
            empty.setLayoutParams(layout);
        }


        /**
         * oppo下移title位置
         */
        boolean isOppOPhone = PhoneStyle.hasNotchInOppo(this);
        if (isOppOPhone){
            LinearLayout.LayoutParams layout = (LinearLayout.LayoutParams) empty.getLayoutParams();
            //oppo 不知道下移多少合适,折中选择了40px
            layout.setMargins(0, 40, 0, 0);
            empty.setLayoutParams(layout);
        }

        /**
         * vivo下移title位置
         */
        boolean isViVoPhone = PhoneStyle.hasNotchInScreenAtVoio(this);
        if (isViVoPhone){
            LinearLayout.LayoutParams layout = (LinearLayout.LayoutParams) empty.getLayoutParams();
            //vivo和oppo一样
            layout.setMargins(0, 40, 0, 0);
            empty.setLayoutParams(layout);
        }
        }

华为手机经过真机测试,位置下移的正好合适,vivo和oppo因为没有刘海手机,没有测试,感觉vivo和oppo都应把刘海的高度给出才好计算。

如果使用刘海手机可以自己在studio里下载模拟器
可参考:[https://developer.android.google.cn/preview/download]

但是使用studio中的模拟器还需要支持Android P,可以下载 Android Studio 3.2 Canary预览版,studio版本能够并行,但是操作同一个项目可能不支持,只能打开一个。

在安装并打开 Android Studio 3.2 之后,按照如下步骤安装 Android P Preview SDK:
点击 Tools > SDK Manager。
在 SDK Platforms 标签下,选择 Android P Preview。
在 SDK Tools 标签下,选择 Android SDK Build-Tools 28-rc1 (或更高版本)。
点击 OK,开始安装。

修改gradle

要全面测试应用的 Android P 兼容性并开始使用新 API,请打开您的模块级 build.gradle 文件并更新 compileSdkVersion 和 targetSdkVersion,如下所示:

android {
    compileSdkVersion 'android-P'

    defaultConfig {
        targetSdkVersion 'P'
    }
    ...
}

具体参考Android开发者官网 :[(https://developer.android.google.cn/preview/setup-sdk)]

google在Android P版本提供了刘海的适配方案,主要时提供了一个类 DisplayCutout
主要有三个模式:

  1. LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT:仅仅当系统提供的bar完全包含了刘海区时才允许window扩展到刘海区,否则window不会和刘海区重叠
  2. LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES:允许window扩展到刘海区(原文说的是短边的刘海区, 目前有刘海的手机都在短边,所以就不纠结了)
  3. LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER:不允许window扩展到刘海区。

允许页面扩展到刘海区

DisplayCutout cutout = view.getRootWindowInsets().getDisplayCutout();
if(cutout != null){
 WindowManager.LayoutParams lp =getWindow().getAttributes();  
 lp.layoutInDisplayCutoutMode=WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER;  
 getWindow().setAttributes(lp);
}

google提供的需要studio升到3.2,现在仅仅时预览版的,只能用于测试,如果测试华为、vivo、oppo手机那就不行了,只能找真机测试,而且我用预览版studio打包出出来的apk安装不了,这就尴尬了,你适配了没法打包,也就没法上线,鸡肋。

oppo官网刘海文档 :[(https://open.oppomobile.com/wiki/doc#id=10159)]
vivo官网刘海文档:[(https://dev.vivo.com.cn/doc/document/info?id=103)]
华为官网刘海文档:[(https://devcenter-test.huawei.com/consumer/cn/devservice/doc/50114)]

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值