public final class CurvedScreenUtils { private static final String TAG = TagPrefix.HRWIDGET + "CurvedScreenUtils"; /** * 單例 */ private static final CurvedScreenUtils INSTANCE = new CurvedScreenUtils(); /** * 應用已做了佈局適配,全面屏會鋪滿屏幕 */ private static final int LAYOUT_IN_DISPLAY_SIDE_MODE_ALWAYS = 1; private static final String SET_DISPLAY_SIDE_MODE = "setDisplaySideMode"; private static final String GET_DISPLAY_SIDE_REGION_SAFE_INSETS = "getDisplaySideRegion"; private static final String GET_SAFE_INSETS = "getSafeInsets"; private int leftSideWidth = 0; private int rightSideWidth = 0; private int topSideWidth = 0; private int bottomSideWidth = 0; private boolean mHasSideWidth; /** * 工具類,私有構造方法 */ private CurvedScreenUtils() { } /** * 獲取單例 * * @return 單例 */ public static CurvedScreenUtils getInstance() { return INSTANCE; } /** * 獲取間距<br/> * 調用方判斷API >=20 * * @param window window */ private void makeSideWidth(final Window window, View view) { if (view == null) { Logger.w(TAG, "makeSideWidth, view is null!"); } View targetView = view == null ? window.getDecorView() : view; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) { targetView.setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() { @Override public WindowInsets onApplyWindowInsets(View view, WindowInsets insets) { WindowManager.LayoutParams params = window.getAttributes(); WindowManagerEx.LayoutParamsEx layoutParamsEx = new WindowManagerEx.LayoutParamsEx(params); Method method = ReflectionUtils .getMethod(layoutParamsEx.getClass(), GET_DISPLAY_SIDE_REGION_SAFE_INSETS, WindowInsets.class); Object object = ReflectionUtils.invoke(method, layoutParamsEx, insets); if (object == null) { // 非超曲面設備 Logger.w(TAG, "CurvedScreenUtils, is not curved screen device!"); } else { Method method0 = ReflectionUtils.getMethod(object.getClass(), GET_SAFE_INSETS); Object rect = ReflectionUtils.invoke(method0, object); if (rect instanceof Rect) { leftSideWidth = ((Rect) rect).left; topSideWidth = ((Rect) rect).top; rightSideWidth = ((Rect) rect).right; bottomSideWidth = ((Rect) rect).bottom; Logger.i(TAG, "leftSideWidth is: " + leftSideWidth + " ;topSideWidth is: " + topSideWidth + " ;rightSideWidth is: " + rightSideWidth + " ;bottomSideWidth is: " + bottomSideWidth); } } return insets; } }); } } /** * 初始化展示模式 這裏的view不能用window的decorView,否則會出現展示異常 * * @param window window * @param view view */ public void setDisplaySideMode(Window window, View view) { if (window == null) { Logger.w(TAG, "window is null!"); return; } Logger.d(TAG, "Emui version is: " + EmuiUtils.VERSION.EMUI_SDK_INT); // 如果版本低於EMUI10,那麼直接返回無需適配 if (!EmuiUtils.isEMUI10xorHigher()) { Logger.w(TAG, "Emui version is too low, do not need curved screen settings!"); return; } try { // 設置曲面屏相關參數 makeCurvedScreenSettings(window); // 獲取間距只需要第一次調用,以後都使用緩存 if (!mHasSideWidth) { Logger.i(TAG, "setDisplaySideMode, makeSideWidth"); mHasSideWidth = true; // 獲取間距 makeSideWidth(window, view); } } catch (RuntimeException e) { Logger.e(TAG, "makeCurvedScreenSettings caused RuntimeException"); } catch (Exception e) { Logger.e(TAG, "makeCurvedScreenSettings failed"); } } /** * 初始化展示模式 只傳入window可能導致的異常:界面全部充滿屏幕可能會和底部的導航欄重合 * * @param window window */ public void setDisplaySideMode(Window window) { setDisplaySideMode(window, null); } private void makeCurvedScreenSettings(Window window) { try { Logger.i(TAG, "makeCurvedScreenSettings!"); WindowManager.LayoutParams params = window.getAttributes(); WindowManagerEx.LayoutParamsEx layoutParamsEx = new WindowManagerEx.LayoutParamsEx(params); Method method = ReflectionUtils.getMethod(layoutParamsEx.getClass(), SET_DISPLAY_SIDE_MODE, int.class); if (null != method) { ReflectionUtils.invoke(method, layoutParamsEx, LAYOUT_IN_DISPLAY_SIDE_MODE_ALWAYS); setAttributes(window, params); } } catch (RuntimeException e) { Logger.e(TAG, "makeCurvedScreenSettings failed"); } catch (Exception e) { Logger.e(TAG, "makeCurvedScreenSettings failed"); } } private void setAttributes(Window window, WindowManager.LayoutParams params) { if (window != null && params != null) { window.setAttributes(params); } } /** * 該方法會修改view左右間距爲#getInstance()#getLeftSideWidth() 長度 * 原來view的左右間距/margin會被覆蓋,特別處理需要自己修改,非超曲面屏不會對view修改 * @param padding 是否是內邊距padding,否則是margin * @param views 需要設置的view */ public static void offsetViewEdge(boolean padding, View... views) { if (views != null) { int oldStart = INSTANCE.getLeftSideWidth(); int oldEnd = INSTANCE.getRightSideWidth(); // 沒有邊距,非超曲面屏 if (oldStart == 0 && oldEnd == 0) { return; } for (View view : views) { if (view == null) { Logger.w(TAG, "view is null continue next view"); continue; } if (padding) { view.setPadding(INSTANCE.getLeftSideWidth(), view.getPaddingTop(), INSTANCE.getRightSideWidth(), view.getPaddingBottom()); } else { ViewGroup.MarginLayoutParams lp = ViewUtils.getLayoutParams(view, ViewGroup.MarginLayoutParams.class); if (lp != null) { int oldTop = lp.topMargin; int oldBottom = lp.bottomMargin; lp.setMarginStart(oldStart); lp.topMargin = oldTop; lp.setMarginEnd(oldEnd); lp.bottomMargin = oldBottom; ViewUtils.setLayoutParams(view, lp); } } } } } /** * 獲取左邊距 * * @return 左邊距 */ public int getLeftSideWidth() { return MultiWindowUtils.isInMultiWindowMode() ? 0 : leftSideWidth; } /** * 獲取界面左間距(含曲面屏動態邊距) * * @return 左邊距 */ public int getPageCommonPaddingStart() { return getLeftSideWidth() + ResUtils.getDimensionPixelSize(R.dimen.page_common_padding_start); } /** * 獲取界面右間距(含曲面屏動態邊距) * * @return 右邊距 */ public int getPageCommonPaddingEnd() { return getRightSideWidth() + ResUtils.getDimensionPixelSize(R.dimen.page_common_padding_start); } /** * 獲取右邊距 * * @return 右邊距 */ public int getRightSideWidth() { return MultiWindowUtils.isInMultiWindowMode() ? 0 : rightSideWidth; } /** * 獲取上邊距 * * @return 上邊距 */ public int getTopSideWidth() { return MultiWindowUtils.isInMultiWindowMode() ? 0 : topSideWidth; } /** * 獲取下邊距 * * @return 下邊距 */ public int getBottomSideWidth() { return MultiWindowUtils.isInMultiWindowMode() ? 0 : bottomSideWidth; } }
超曲面屏工具類
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.