刘海屏适配

  • 适配逻辑


对于有状态栏的页面不需要适配,因为刘海位置包含在状态栏高度中,我们需要适配的是没有状态栏的页面

  • 适配流程
    1. 应用页面设置使用刘海区显示

或者使用代码
/*刘海屏全屏显示FLAG*/
public static final int FLAG_NOTCH_SUPPORT=0x00010000;
/**
 * 设置应用窗口在华为刘海屏手机使用刘海区
 * @param window 应用页面window对象
 */
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(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) {
        Log.e("test", "hw add notch screen flag api error");
    } catch (Exception e) {
        Log.e("test", "other Exception");
    }
}
2\. 设置屏幕最大宽高比



3\. 判断是否为刘海屏,包括小米,华为,vivo等不同型号的检测
/**
 * 判断是否是刘海屏
 */
public static boolean hasNotchScreen(Context context){
    if(mChecked){
        return sHasNotchScreen;
    }
    if (hasNotchAtXiaomi(context) || hasNotchAtHuawei(context) || hasNotchAtOPPO(context)
            || hasNotchAtVivo(context)){ //|| isAndroidP(context) != null
        sHasNotchScreen = true;
    }
    else{
        sHasNotchScreen = false;//true for test, false is real!
    }
    sStatusHeight = getSystemStatusHeight(context);
    mChecked = true;
    return sHasNotchScreen;
}

4\. 获取高度并在页面设置占位高度

if(ScreenNotchUtil.hasNotchScreen(this)){
    int i = ScreenNotchUtil.getNotchSize(this)[1];
    if(i>0){
        viewById.setHeight(i);
        viewById.setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
        viewById.setBackgroundColor(Color.BLUE);
        viewById.setVisibility(View.VISIBLE);
    }
}

9.0 google刘海屏适配

getSupportActionBar().hide();
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | 
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); 
//设置页面全屏显示
WindowManager.LayoutParams lp = getWindow().getAttributes();
lp.layoutInDisplayCutoutMode = 
       WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES; 
//设置页面延伸到刘海区显示
getWindow().setAttributes(lp);
  • 附上完整工具类

public class ScreenNotchUtil {

    public static final String ROM_MIUI = "MIUI";
    public static final String ROM_EMUI = "EMUI";
    public static final String ROM_FLYME = "FLYME";
    public static final String ROM_OPPO = "OPPO";
    public static final String ROM_SMARTISAN = "SMARTISAN";
    public static final String ROM_VIVO = "VIVO";
    public static final String ROM_QIKU = "QIKU";

    private static final String KEY_VERSION_MIUI = "ro.miui.ui.version.name";
    private static final String KEY_VERSION_EMUI = "ro.build.version.emui";
    private static final String KEY_VERSION_OPPO = "ro.build.version.opporom";
    private static final String KEY_VERSION_SMARTISAN = "ro.smartisan.version";
    private static final String KEY_VERSION_VIVO = "ro.vivo.os.version";

    static  boolean mChecked;
    static  boolean sHasNotchScreen;
    static int sStatusHeight = 0;
    /**
     * 判断是否是刘海屏
     */
    public static boolean hasNotchScreen(Context context){
        if(mChecked){
            return sHasNotchScreen;
        }
        if (hasNotchAtXiaomi(context) || hasNotchAtHuawei(context) || hasNotchAtOPPO(context)
                || hasNotchAtVivo(context)){ //|| isAndroidP(context) != null
            sHasNotchScreen = true;
        }
        else{
            sHasNotchScreen = false;//true for test, false is real!
        }
        sStatusHeight = getSystemStatusHeight(context);
        mChecked = true;
        return sHasNotchScreen;
    }

    public static int getSystemStatusHeight(Context context)
    {
        try
        {
            if(mChecked){
                return sStatusHeight;
            }
            Class c = Class.forName("com.android.internal.R$dimen");
            Object obj = c.newInstance();
            Field field = c.getField("status_bar_height");
            int x = Integer.parseInt(field.get(obj).toString());
            int y = context.getResources().getDimensionPixelSize(x);
            return y;
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        return 0;
    }


    public static void checkRom() {
        String brand = Build.BRAND.toUpperCase();
        String rom = null;
        if (!TextUtils.isEmpty(getProp(KEY_VERSION_MIUI))) {
            rom = ROM_MIUI;
        } else if (!TextUtils.isEmpty(getProp(KEY_VERSION_EMUI))) {
            rom = ROM_EMUI;
        } else if (!TextUtils.isEmpty(getProp(KEY_VERSION_OPPO))) {
            rom = ROM_OPPO;
        } else if (!TextUtils.isEmpty(getProp(KEY_VERSION_VIVO))) {
            rom = ROM_VIVO;
        } else {
            if (brand.contains("HUAWEI")) {
                rom = ROM_EMUI;
            } else if (brand.contains("OPPO")) {
                rom = ROM_OPPO;
            } else if (brand.contains("VIVO")) {
                rom = ROM_VIVO;
            } else if (brand.contains("XIAOMI")) {
                rom = ROM_MIUI;
            }
            else {
                rom = Build.MANUFACTURER.toUpperCase();
            }
        }
    }

    public static String getProp(String name) {
        String line = null;
        BufferedReader input = null;
        try {
            Process p = Runtime.getRuntime().exec("getprop " + name);
            input = new BufferedReader(new InputStreamReader(p.getInputStream()), 1024);
            line = input.readLine();
            input.close();
        } catch (Exception ex) {
            return null;
        } finally {
            if (input != null) {
                try {
                    input.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return line;
    }

    /**
     * 小米刘海屏判断.
     * @return 0 if it is not notch ; return 1 means notch
     * @throws IllegalArgumentException if the key exceeds 32 characters
     */
    private static int getInt(String key, Context context) {
        int result = 0;
        if (isXiaomi()){
            try {
                ClassLoader classLoader = context.getClassLoader();
                @SuppressWarnings("rawtypes")
                Class SystemProperties = classLoader.loadClass("android.os.SystemProperties");
                //参数类型
                @SuppressWarnings("rawtypes")
                Class[] paramTypes = new Class[2];
                paramTypes[0] = String.class;
                paramTypes[1] = int.class;
                Method getInt = SystemProperties.getMethod("getInt", paramTypes);
                //参数
                Object[] params = new Object[2];
                params[0] = new String(key);
                params[1] = new Integer(0);
                result = (Integer) getInt.invoke(SystemProperties, params);

            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    /**
     *小米刘海屏判断
     */
    public static boolean hasNotchAtXiaomi(Context context){
        boolean hasNotch = getInt("ro.miui.notch",context) == 1;
        return hasNotch;
    }
    /**
     * 华为刘海屏判断
     * @return
     */
    public static boolean hasNotchAtHuawei(Context context) {
        boolean ret = false;
        try {
            ClassLoader classLoader = context.getClassLoader();
            Class HwNotchSizeUtil = classLoader.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;
        }
    }

    public static final int VIVO_NOTCH = 0x00000020;//是否有刘海
    public static final int VIVO_FILLET = 0x00000008;//是否有圆角

    /**
     * VIVO刘海屏判断
     * @return
     */
    public static boolean hasNotchAtVivo(Context context) {
        boolean ret = false;
        try {
            ClassLoader classLoader = context.getClassLoader();
            Class FtFeature = classLoader.loadClass("android.util.FtFeature");
            Method method = FtFeature.getMethod("isFeatureSupport", int.class);
            ret = (boolean) method.invoke(FtFeature, VIVO_NOTCH);
        } catch (ClassNotFoundException e) {
        } catch (NoSuchMethodException e) {
        } catch (Exception e) {
        } finally {
            return ret;
        }
    }
    /**
     * OPPO刘海屏判断
     * @return
     */
    public static boolean hasNotchAtOPPO(Context context) {
        boolean hasNotch =  context.getPackageManager().hasSystemFeature("com.oppo.feature.screen.heteromorphism");
        return hasNotch;
    }

    /**
     * Android P 刘海屏判断
     */
    // 是否是小米手机
    public static boolean isXiaomi() {
        return "Xiaomi".equals(Build.MANUFACTURER);
    }

    /**
     * 获取刘海屏的尺寸信息
     * @param context
     * @return
     */
    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 ignored) {

        } catch (NoSuchMethodException ignored) {

        } catch (Exception ignored) {

        } finally {

            return ret;

        }
    }
}

76369452cd1980642084f15424306ab.jpg

06303f33f818e849e7c618d3c9248b7.jpg

你可能感兴趣的:(刘海屏适配)