天天看點

全屏時、劉海屏适配問題

劉海屏的适配

  • 關于劉海屏适配問題、android跟風劉海屏、在android P(9.0 API 28)才能用原生的android 劉海屏适配、在Android N(7.0 API 24)到 android P(9.0 API 28)期間、很多廠商都對自己的硬體做了提前的适配,是以需要我們對其做适配、
  • 何時才需要适配、設定全屏模式下,需要對劉海屏進行适配。不然會存在這樣的問題U展示不全問題、在android N 以下的設定全屏沒問題。在N - P 有劉海屏情況下 則會有UI顯示異常(底部ui顯示不全)。故設定一個包裹容器包裹、
  • 怎麼适配呢、
  1. 判斷版本區間(android N 以下、android N - android P、 Android P 以上)
  2. android N 以下, 直接預設的設定全屏。 android N 以上 直接如果不是劉海屏 則設定為全屏,如果是劉海屏則不進行設定。
requestWindowFeature(Window.FEATURE_NO_TITLE)
            window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                    WindowManager.LayoutParams.FLAG_FULLSCREEN)
複制代碼
           
  1. 不同的廠商劉海屏的适配也不同具體參考對應的開發者平台。以下代碼說明如何查詢是否是劉海屏,以及擷取劉海屏的高度。若類似于一加手機沒有開發者平台交流的、隻好單獨拎出來,判斷。
擷取到劉海屏的高度、若沒有,則傳回0
// ------------------------------ 劉海屏處理 ------------------------------
    private static final String ONEPLUS6 = "ONEPLUS A6000";

    /**
     * 擷取劉海的高度
     *
     * @param context
     * @return
     */
    public static int obtainCutoutHeight(Context context) {
        // 7.0以下不會有劉海,避免不必要的反射性能損耗
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
            return 0;
        }
         /*if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            // ------------------------------ Android P 版本 及以上 的統一适配 ------------------------------
            val displayCutout: DisplayCutout? = rootWindowInsets.displayCutout
            if (displayCutout != null) {
                L.e("TAG", "安全區域距離螢幕頂部的距離 SafeInsetTop:" + displayCutout.safeInsetTop)
                return displayCutout.safeInsetTop
            }
            return 0
        }*/

        if (OSUtils.isEMUI() && OSUtils.hasHWNotchInScreen(context)) {
            return OSUtils.getHWNotchSize(context)[1];
        }

        if (OSUtils.isMIUI() && OSUtils.hasMIUINotchInScreen()) {
            return OSUtils.getMIUINotchSize(context);
        }

        // oppo固定80px
        if (OSUtils.hasOppoNotchInScreen(context)) {
            return 80;
        }

        if (OSUtils.hasVivoNotchInScreen(context)) {
            return obtainStatusBarHeight(context);
        }

        if (ONEPLUS6.equals(Build.MODEL)) {
            return obtainStatusBarHeight(context);
        }

        return 0;
    }

    public static int obtainStatusBarHeight(Context context) {
        int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
        int statusBarHeight = 0;
        if (resourceId > 0) {
            statusBarHeight = context.getResources().getDimensionPixelSize(resourceId);
        }
        return statusBarHeight;
    }
複制代碼
           
判斷是不是華為
/**
     * 判斷是否為emui
     * Is emui boolean.
     *
     * @return the boolean
     */
    public static boolean isEMUI() {
        String property = getSystemProperty(KEY_EMUI_VERSION_NAME, "");
        return !TextUtils.isEmpty(property);
    }
複制代碼
           
華為是否有劉海屏
activity 标簽下添加
<meta-data android:name="android.notch_support" android:value="true"/>
複制代碼
           
/**
     * 判斷是否是華為劉海屏
     *
     * @param context
     * @return
     */
    public static boolean hasHWNotchInScreen(Context context) {

        boolean hasNotch = false;
        try {
            ClassLoader classLoader = context.getClassLoader();
            Class hwNotchSizeUtil = classLoader.loadClass("com.huawei.android.util.HwNotchSizeUtil");
            Method method = hwNotchSizeUtil.getMethod("hasNotchInScreen");
            hasNotch = (Boolean) method.invoke(hwNotchSizeUtil);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return hasNotch;
    }

複制代碼
           
擷取華為劉海屏高度
/**
     * 擷取華為劉海的高寬
     *
     * @param context 上下文對象
     * @return [0]值為劉海寬度int;[1]值為劉海高度
     */
    public static int[] getHWNotchSize(Context context) {
        int[] size = new int[2];
        try {
            ClassLoader classLoader = context.getClassLoader();
            Class hwNotchSizeUtil = classLoader.loadClass("com.huawei.android.util.HwNotchSizeUtil");
            Method method = hwNotchSizeUtil.getMethod("getNotchSize");
            size = (int[]) method.invoke(hwNotchSizeUtil);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return size;
    }


複制代碼
           
MIUI 是否有劉海屏、及劉海屏的高度
/**
     * 判斷是否為miui
     * Is miui boolean.
     *
     * @return the boolean
     */
    public static boolean isMIUI() {
        String property = getSystemProperty(KEY_MIUI_VERSION_NAME, "");
        return !TextUtils.isEmpty(property);
    }
    
/**
     * 隻适用于判斷MIUI 是否有劉海屏
     * SystemProperties.getInt("ro.miui.notch", 0) == 1;
     *
     * @return
     */
    public static boolean hasMIUINotchInScreen() {
        try {
            Class<?> clz = Class.forName("android.os.SystemProperties");
            Method get = clz.getMethod("getInt", String.class, String.class);
            return (int) get.invoke(clz, "ro.miui.notch", -1) == 1;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 擷取MIUI 的劉海屏高度
     *
     * @param context
     */
    public static int getMIUINotchSize(Context context) {
        int resourceId = context.getResources().getIdentifier("notch_height", "dimen", "android");
        if (resourceId > 0) {
            return context.getResources().getDimensionPixelSize(resourceId);
        }
        return 0;
    }
複制代碼
           
oppo 是否有劉海屏、并統一設定為80px
/**
     * 是否是Oppo的劉海屏
     *
     * @param context
     * @return
     */
    public static boolean hasOppoNotchInScreen(Context context) {
        return context.getPackageManager().hasSystemFeature("com.oppo.feature.screen.heteromorphism");
    }

複制代碼
           
vivo 是否支援劉海屏、 并設定高度為狀态欄高度
/**
     * Vivo手機劉海屏
     *
     * @param context
     * @return
     */
    /**
     * 是否有劉海
     */
    public static final int VIVO_NOTCH = 0x00000020;
    /**
     * 是否有圓角
     */
    public static final int VIVO_FILLET = 0x00000008;

    public static boolean hasVivoNotchInScreen(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) {
            Log.e("Notch", "hasNotchAtVoio ClassNotFoundException");
        } catch (NoSuchMethodException e) {
            Log.e("Notch", "hasNotchAtVoio NoSuchMethodException");
        } catch (Exception e) {
            Log.e("Notch", "hasNotchAtVoio Exception");
        } finally {
            return ret;
        }
    }
複制代碼
           
自定義包裹的LinearLayout
/**
 * @author:Created by Mrko
 * @description: 劉海屏适配類
 */
class DisplayCutoutView : LinearLayout {
    private lateinit var emptyView: View

    constructor(context: Context) : this(context, null)
    constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
        initView()
    }

    fun initView() {
        val viewParams = ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.WRAP_CONTENT,
                StatusBarUtils.obtainCutoutHeight(context))
        emptyView = View(context)
        emptyView.layoutParams = viewParams
        addView(emptyView)
    }

}
複制代碼
           
運用地方
<com.xxx.DisplayCutoutView
        android:id="@+id/rl_display"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/primary_pressed"
        android:orientation="vertical">

        <com.xxx.hintView
            android:id="@+id/color_detail_hint"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:textColor="@color/white"
            android:textSize="14sp" />
    </com.xxx.DisplayCutoutView>

複制代碼
           
Activity 進行相容性适配
override fun beforeSetContentView() {

        /*L.e("mrko--->", "手機品牌--> \n  ${Build.PRODUCT} + \n
                                        "${Build.DEVICE} + \n
                                        "${Build.BOARD} + \n
                                        "${Build.MANUFACTURER} + \n
                                        "${Build.BRAND} + \n
                                        "${Build.MODEL} + \n
                                        "${Build.HARDWARE} + \n
                                        "${Build.MANUFACTURER} + \n
                                        "${Build.ID} + \n
                                        "${Build.DISPLAY} + \n ")*/
        if (StatusBarUtils.obtainCutoutHeight(mContext) == 0) {
            requestWindowFeature(Window.FEATURE_NO_TITLE)
            window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                    WindowManager.LayoutParams.FLAG_FULLSCREEN)
        }
        super.beforeSetContentView()
    }
複制代碼
           

附上參考連結 juejin.im/post/5b1930…

轉載于:https://juejin.im/post/5b7c01a6f265da43445f5e8d

繼續閱讀