其他适配
状态栏导航栏高度适配
状态栏
状态栏是否显示
/**
* Return whether the status bar is visible.
* @param activity The activity.
* @return {@code true}: yes<br>{@code false}: no
*/
public static boolean isStatusBarVisible(@NonNull final Activity activity) {
int flags = activity.getWindow().getAttributes().flags;
return (flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) == 0;
}
状态栏高度
/**
* Return the status bar's height.
*
* @return the status bar's height
*/
public static int getStatusBarHeight() {
if (mStatusBarHeight <= 0) {
Resources resources = Resources.getSystem();
int resourceId = resources.getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
mStatusBarHeight = resources.getDimensionPixelSize(resourceId);
}
}
return mStatusBarHeight;
}
导航栏
导航栏是否显示
/**
* Return whether the navigation bar visible.
*
* @param window The window.
* @return {@code true}: yes<br>{@code false}: no
*/
public static boolean isNavBarVisible(@NonNull final Window window) {
boolean isNoLimits = (window.getAttributes().flags
& WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS) != 0;
if (isNoLimits) return false;
View decorView = window.getDecorView();
int visibility = decorView.getSystemUiVisibility();
return (visibility & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
}
导航栏高度
/**
* Return the navigation bar's height.
*
* @return the navigation bar's height
*/
public static int getNavBarHeight() {
Resources res = Resources.getSystem();
int resourceId = res.getIdentifier("navigation_bar_height", "dimen", "android");
if (resourceId != 0) {
return res.getDimensionPixelSize(resourceId);
} else {
return 0;
}
}
华为底部手机导航栏适配
华为 EMUI 底部导航栏,有可以手动设置显示和隐藏底部导航栏的按钮
糗百方案
public static int getNavigationBarHeight(Activity activity) {
if (activity == null) {
return 0;
}
if (!isNavigationBarShow(activity)) {
return 0;
}
Resources resources = activity.getResources();
int resourceId = resources.getIdentifier("navigation_bar_height",
"dimen", "android");
int height = 0;
if (resourceId > 0) {
//获取NavigationBar的高度
height = resources.getDimensionPixelSize(resourceId);
}
return height;
}
public static boolean isNavigationBarShow(Activity context) {
if (context == null) {
return false;
}
if (isFullScreen(context)) {
if (OSUtils.isMIUI()) {//小米系统判断虚拟键是否显示方法
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
if (Settings.Global.getInt(context.getContentResolver(), "force_fsg_nav_bar", 0) != 0) {
//开启手势,不显示虚拟键
return false;
}
}
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
Display display = context.getWindowManager().getDefaultDisplay();
Point size = new Point();
Point realSize = new Point();
display.getSize(size);
display.getRealSize(realSize);
return realSize.y != size.y;
} else {
boolean menu = ViewConfiguration.get(context).hasPermanentMenuKey();
boolean back = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK);
if (menu || back) {
return false;
} else {
return true;
}
}
}
获取导航栏 NavigationBarUtils 是否开启,和高度的最优方案
上面默认的方式,可能有些机型不行
public final class NavgationBarUtils {
/**
* @return false 关闭了NavgationBar ,true 开启了
*/
public static boolean isNavBarVisible(Context context) {
ViewGroup rootLinearLayout = findRootLinearLayout(context);
int navigationBarHeight = 0;
if (rootLinearLayout != null) {
ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) rootLinearLayout.getLayoutParams();
navigationBarHeight = layoutParams.bottomMargin;
}
if (navigationBarHeight == 0) {
return false;
} else {
return true;
}
}
/**
* 导航栏高度,关闭的时候返回0,开启时返回对应值
*/
public static int getNavBarHeight(Context context) {
ViewGroup rootLinearLayout = findRootLinearLayout(context);
int navigationBarHeight = 0;
if (rootLinearLayout != null) {
ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) rootLinearLayout.getLayoutParams();
navigationBarHeight = layoutParams.bottomMargin;
}
return navigationBarHeight;
}
/**
* 从R.id.content从上遍历,拿到 DecorView 下的唯一子布局LinearLayout 获取对应的bottomMargin
* 即可得到对应导航栏的高度,0为关闭了或没有导航栏
*/
private static ViewGroup findRootLinearLayout(Context context) {
ViewGroup onlyLinearLayout = null;
try {
Window window = getWindow(context);
if (window != null) {
ViewGroup decorView = (ViewGroup) getWindow(context).getDecorView();
Activity activity = getActivity(context);
View contentView = activity.findViewById(android.R.id.content);
if (contentView != null) {
View tempView = contentView;
while (tempView.getParent() != decorView) {
ViewGroup parent = (ViewGroup) tempView.getParent();
if (parent instanceof LinearLayout) {
//如果style设置了不带toolbar,mContentView上层布局会由原来的 ActionBarOverlayLayout->FitWindowsLinearLayout)
if (parent instanceof FitWindowsLinearLayout) {
tempView = parent;
continue;
} else {
onlyLinearLayout = parent;
break;
}
} else {
tempView = parent;
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return onlyLinearLayout;
}
private static Window getWindow(Context context) {
if (getAppCompActivity(context) != null) {
return getAppCompActivity(context).getWindow();
} else {
return scanForActivity(context).getWindow();
}
}
private static Activity getActivity(Context context) {
if (getAppCompActivity(context) != null) {
return getAppCompActivity(context);
} else {
return scanForActivity(context);
}
}
private static AppCompatActivity getAppCompActivity(Context context) {
if (context == null) return null;
if (context instanceof AppCompatActivity) {
return (AppCompatActivity) context;
} else if (context instanceof ContextThemeWrapper) {
return getAppCompActivity(((ContextThemeWrapper) context).getBaseContext());
}
return null;
}
private static Activity scanForActivity(Context context) {
if (context == null) return null;
if (context instanceof Activity) {
return (Activity) context;
} else if (context instanceof ContextWrapper) {
return scanForActivity(((ContextWrapper) context).getBaseContext());
}
return null;
}
}
完整
生产环境可用
// BarUtils
public final class BarUtils {
// ====== statusbar ======
private static int mStatusBarHeight;
/**
* Return whether the status bar is visible.
*
* @param activity The activity.
* @return {@code true}: yes<br>{@code false}: no
*/
public static boolean isStatusBarVisible(@NonNull final Activity activity) {
int flags = activity.getWindow().getAttributes().flags;
return (flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) == 0;
}
/**
* Return the status bar's height.
*
* @return the status bar's height
*/
public static int getStatusBarHeight() {
if (mStatusBarHeight <= 0) {
Resources resources = Resources.getSystem();
int resourceId = resources.getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
mStatusBarHeight = resources.getDimensionPixelSize(resourceId);
}
}
return mStatusBarHeight;
}
// ====== navigationbar ======
/**
* Return whether the navigation bar visible.
*
* @param activity The activity.
* @return {@code true}: yes<br>{@code false}: no
*/
public static boolean isNavBarVisible(@NonNull final Activity activity) {
return isNavBarVisible(activity.getWindow());
}
/**
* Return whether the navigation bar visible. 没有考虑到沉浸式透明导航栏情况
*
* @param window The window.
* @return {@code true}: yes<br>{@code false}: no
*/
public static boolean isNavBarVisible(@NonNull final Window window) {
boolean isNoLimits = (window.getAttributes().flags
& WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS) != 0;
if (isNoLimits) return false;
View decorView = window.getDecorView();
int visibility = decorView.getSystemUiVisibility();
return (visibility & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
}
/**
* Return the navigation bar's height. 没有考虑到沉浸式透明导航栏情况
*
* @return the navigation bar's height
*/
public static int getNavBarHeight() {
Resources res = Resources.getSystem();
int resourceId = res.getIdentifier("navigation_bar_height", "dimen", "android");
if (resourceId != 0) {
return res.getDimensionPixelSize(resourceId);
} else {
return 0;
}
}
/**
* @return false 关闭了NavgationBar ,true 开启了。考虑了沉浸式导航栏情况
*/
public static boolean isNavBarVisible(Context context) {
ViewGroup rootLinearLayout = findRootLinearLayout(context);
int navigationBarHeight = 0;
if (rootLinearLayout != null) {
ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) rootLinearLayout.getLayoutParams();
navigationBarHeight = layoutParams.bottomMargin;
}
if (navigationBarHeight == 0) {
return false;
} else {
return true;
}
}
/**
* 导航栏高度,关闭的时候返回0,开启时返回对应值。考虑了沉浸式导航栏情况
*/
public static int getNavBarHeight(Context context) {
ViewGroup rootLinearLayout = findRootLinearLayout(context);
int navigationBarHeight = 0;
if (rootLinearLayout != null) {
ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) rootLinearLayout.getLayoutParams();
navigationBarHeight = layoutParams.bottomMargin;
}
return navigationBarHeight;
}
/**
* 从R.id.content从上遍历,拿到 DecorView 下的唯一子布局LinearLayout 获取对应的bottomMargin
* 即可得到对应导航栏的高度,0为关闭了或没有导航栏
*/
private static ViewGroup findRootLinearLayout(Context context) {
ViewGroup onlyLinearLayout = null;
try {
Window window = getWindow(context);
if (window != null) {
ViewGroup decorView = (ViewGroup) getWindow(context).getDecorView();
Activity activity = getActivity(context);
View contentView = activity.findViewById(android.R.id.content);
if (contentView != null) {
View tempView = contentView;
while (tempView.getParent() != decorView) {
ViewGroup parent = (ViewGroup) tempView.getParent();
if (parent instanceof LinearLayout) {
//如果style设置了不带toolbar,mContentView上层布局会由原来的 ActionBarOverlayLayout->FitWindowsLinearLayout)
if (parent instanceof FitWindowsLinearLayout) {
tempView = parent;
continue;
} else {
onlyLinearLayout = parent;
break;
}
} else {
tempView = parent;
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return onlyLinearLayout;
}
private static Window getWindow(Context context) {
if (getAppCompActivity(context) != null) {
return getAppCompActivity(context).getWindow();
} else {
return scanForActivity(context).getWindow();
}
}
private static Activity getActivity(Context context) {
if (getAppCompActivity(context) != null) {
return getAppCompActivity(context);
} else {
return scanForActivity(context);
}
}
private static AppCompatActivity getAppCompActivity(Context context) {
if (context == null) return null;
if (context instanceof AppCompatActivity) {
return (AppCompatActivity) context;
} else if (context instanceof ContextThemeWrapper) {
return getAppCompActivity(((ContextThemeWrapper) context).getBaseContext());
}
return null;
}
private static Activity scanForActivity(Context context) {
if (context == null) return null;
if (context instanceof Activity) {
return (Activity) context;
} else if (context instanceof ContextWrapper) {
return scanForActivity(((ContextWrapper) context).getBaseContext());
}
return null;
}
}