package com.example.basecore.util; import android.annotation.TargetApi; import android.app.Activity; import android.app.Dialog; import android.content.Context; import android.content.res.Resources; import android.graphics.Point; import android.graphics.Rect; import android.graphics.RectF; import android.os.Build; import android.provider.Settings; import android.util.DisplayMetrics; import android.view.Display; import android.view.View; import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager; import static android.content.Context.WINDOW_SERVICE; import static androidx.recyclerview.widget.RecyclerView.NO_ID; import androidx.annotation.NonNull; public class ScreenUtil { private static final String NAVIGATION = "navigationBarBackground"; public static int getScreenWidth(Context context) { return ScreenUtils.getAppDisplayWidth(context); } public static int getScreenHeight(Context context) { return ScreenUtils.getDeviceScreenHeight(context); } public static int getScreenHeightNoNav(Context context) { return getScreenHeight(context) - getBottomNavBarHeight(context); } /** * 需要传递 application的 context ,能够适配更多手机 * @param context application * @return 不包含导航栏的高度 */ public static int getCompatScreenHeightNoNav(Context context){ int screenHeight = getScreenHeight(context); if (hasNavigationBar(context)) { screenHeight -= getNavigationBarHeight(context); } return screenHeight; } public static double getScreenInches(Context context) { DisplayMetrics dm = context.getResources().getDisplayMetrics(); int width = dm.widthPixels; int height = dm.heightPixels; double wi = (double) width / (double) dm.xdpi; double hi = (double) height / (double) dm.ydpi; double x = Math.pow(wi, 2); double y = Math.pow(hi, 2); double screenInches = Math.sqrt(x + y); return screenInches; } public static double getScreenWidthInches(Context context) { DisplayMetrics dm = context.getResources().getDisplayMetrics(); int width = dm.widthPixels; double wi = (double) width / (double) dm.xdpi; return wi; } public static double getScreenHeightInches(Context context) { DisplayMetrics dm = context.getResources().getDisplayMetrics(); int height = dm.heightPixels; double hi = (double) height / (double) dm.ydpi; return hi; } public static RectF getGlobalVisibleRect(View view) { if (null != view) { Rect rect = new Rect(); view.getGlobalVisibleRect(rect); return new RectF(rect); } return null; } public static RectF getGlobalRect(View view) { if (null != view) { RectF rect = new RectF(); View currentView = view; // currentView.getLocalVisibleRect(rect); //这种方式无法获取屏幕外部区域值 int[] xy = new int[2]; currentView.getLocationInWindow(xy); float width = currentView.getScaleX() * currentView.getWidth(); float height = currentView.getScaleY() * currentView.getHeight(); rect.set(xy[0], xy[1], xy[0] + width, xy[1] + height); return rect; } return null; } private static boolean hasNavBar(Context context) { WindowManager wm = (WindowManager) context .getSystemService(WINDOW_SERVICE); if (wm != null) { Display display = wm.getDefaultDisplay(); Point size = new Point(); Point realSize = new Point(); display.getSize(size); display.getRealSize(realSize); return realSize.y != size.y; } else { return true; } } public static boolean hasNavBar2(Activity activity) { ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView(); int count = decorView.getChildCount(); for (int i = 0; i < count; i++) { View view = decorView.getChildAt(i); if (view.getId() != NO_ID && NAVIGATION.equals(activity.getResources().getResourceEntryName(view.getId())) && view.getVisibility() == View.VISIBLE) { return true; } } return false; } private static boolean xiaomiHasNavBar(Context context) { return Settings.Global.getInt(context.getContentResolver(), "force_fsg_nav_bar", 0) != 0; } public static int getBottomNavBarHeight(Context context) { if (!hasNavBar(context)) { return 0; } if (context instanceof Activity) { if (!hasNavBar2((Activity) context)) { return 0; } } Resources resources = context.getResources(); int resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android"); if (resourceId > 0) { return resources.getDimensionPixelSize(resourceId); } return 0; } public static int getTopNavBarHeight(Context context) { Resources resources = context.getResources(); int resourceId = resources.getIdentifier("status_bar_height", "dimen", "android"); if (resourceId > 0) { return resources.getDimensionPixelSize(resourceId); } return 0; } /** * 判断当前view是否出现在可视窗口 * * @param view 视图 * @param forceInside 是否所有区域都在出现在屏幕内 * @return */ public static boolean isViewInScreen(View view, boolean forceInside) { if (null == view) { return false; } Context context = view.getContext(); RectF rect = getGlobalRect(view); return isRectInScreen(context, rect, forceInside); } /** * 判断当前view是否完全可见 * @return */ public static boolean isViewCovered(View view) { Rect currentViewRect = new Rect(); boolean partVisible = view.getGlobalVisibleRect(currentViewRect); boolean totalHeightVisible = (currentViewRect.bottom - currentViewRect.top) >= view.getMeasuredHeight(); boolean totalWidthVisible = (currentViewRect.right - currentViewRect.left) >= view.getMeasuredWidth(); boolean totalViewVisible = partVisible && totalHeightVisible && totalWidthVisible; if (!totalViewVisible)//if any part of the view is clipped by any of its parents,return true return true; if (view.getParent() instanceof ViewGroup) { ViewGroup currentParent = (ViewGroup) view.getParent(); if (currentParent.getVisibility() != View.VISIBLE)//if the parent of view is not visible,return true return true; if (view.getBottom() <= currentParent.getBottom()) { return false; } } return true; } /** * 判断当前rect是否出现在可视窗口 * * @param context 上下文 * @param rect 视图的矩阵区域 * @param forceInside 是否所有区域都在出现在屏幕内 * @return */ public static boolean isRectInScreen(Context context, RectF rect, boolean forceInside) { if (null == context || null == rect) { return false; } Rect screen = ScreenUtils.getAppDisplayRect(context, 0); if (forceInside) { //任何一个顶点 超出屏幕区域,则判定为超出屏幕区域 boolean invalid = (rect.left > screen.width() || rect.left < 0) || (rect.right > screen.width() || rect.right < 0)// || (rect.top > screen.height() || rect.top < 0)// || (rect.bottom > screen.height() || rect.bottom < 0); return !invalid; } else { //任何一个顶点在屏幕区域内,则判定为出现在屏幕中 return (rect.left < screen.width() && rect.left > 0) || (rect.right < screen.width() && rect.right > 0)// || (rect.top < screen.height() && rect.top > 0)// || (rect.bottom < screen.height() && rect.bottom > 0); } } /** * 隐藏NavBar */ public static void hideNavBar(Context mContext, Dialog mDialog) { if (!hasNavBar(mContext)||mDialog==null) { return; } Window window = mDialog.getWindow(); if (window != null) { mDialog.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION); mDialog.getWindow().getDecorView().setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() { @Override public void onSystemUiVisibilityChange(int visibility) { int uiOptions = View.SYSTEM_UI_FLAG_LAYOUT_STABLE | //布局位于状态栏下方 View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | //全屏 View.SYSTEM_UI_FLAG_FULLSCREEN | //隐藏导航栏 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; uiOptions |= 0x00001000; mDialog.getWindow().getDecorView().setSystemUiVisibility(uiOptions); } }); } } public static Rect getScreenRectNoStatusAndNav(@NonNull Context context) { Rect deviceScreenRect = ScreenUtils.getDeviceScreenRect(context, 0); Rect displayRect = new Rect(); displayRect.left = deviceScreenRect.left; displayRect.top = deviceScreenRect.top + ScreenUtils.getSystemStatusBarHeight(context); displayRect.right = deviceScreenRect.right; if (ScreenUtil.hasNavigationBar(context)) { displayRect.bottom = deviceScreenRect.bottom - getBottomNavBarHeight(context); } else { displayRect.bottom = deviceScreenRect.bottom; } return displayRect; } /** * 兼容全面屏是否存在导航栏 * @param context non null * @return true 有导航啦 */ public static boolean hasNavigationBar(Context context) { if (getNavigationBarHeight(context) == 0) { return false; } else if (RomUtils.isHuawei() && isHuaWeiHideNav(context)) { return false; } else if (RomUtils.isXiaomi() && xiaomiHasNavBar(context)) { return false; } else if (RomUtils.isVivo() && isVivoFullScreen(context)) { return false; } else { return isHasNavigationBar(context); } } private static boolean isHuaWeiHideNav(Context context) { return Settings.Global.getInt(context.getContentResolver(), "navigationbar_is_min", 0) != 0; } private static boolean isVivoFullScreen(Context context) { return Settings.Secure.getInt(context.getContentResolver(), "navigation_gesture_on", 0) != 0; } private static boolean isHasNavigationBar(Context context){ WindowManager windowManager = (WindowManager) context.getSystemService(WINDOW_SERVICE); Display d = windowManager.getDefaultDisplay(); DisplayMetrics realDisplayMetrics = new DisplayMetrics(); d.getRealMetrics(realDisplayMetrics); int realHeight = realDisplayMetrics.heightPixels; int realWidth = realDisplayMetrics.widthPixels; DisplayMetrics displayMetrics = new DisplayMetrics(); d.getMetrics(displayMetrics); int displayHeight = displayMetrics.heightPixels; int displayWidth = displayMetrics.widthPixels; // 部分无良厂商的手势操作,显示高度 + 导航栏高度,竟然大于物理高度,对于这种情况,直接默认未启用导航栏 if (displayHeight + getNavigationBarHeight(context)> realHeight) return false; return realWidth - displayWidth > 0 || realHeight - displayHeight > 0; } public static int getNavigationBarHeight(Context context) { int result = 0; int resourceId = context.getResources().getIdentifier("navigation_bar_height", "dimen", "android"); if (resourceId > 0) { result = context.getResources().getDimensionPixelSize(resourceId); } return result; } }