Android应用:StatusBar状态栏、NavigationBar虚拟按键栏、ActionBar标题栏、Window屏幕内容区域等的宽高

时间:2022-10-29 19:24:03

一、屏幕中各种栏目以及屏幕的尺寸

当我们需要计算屏幕中一些元素的高度时,或许需要先获取到屏幕或者各种栏目的高度,下面这个类包含了Status bar状态栏,Navigation bar虚拟按键栏,Action bar标题栏, Window屏幕内容等的宽高的计算,可以带来极大的方便。

因为我在代码中做了比较详尽的注释,在这里不再多阐述,以下是代码:

 /**
* 这个类描述了当前设备的配置中system bar的尺寸(StatusBar状态栏,NavigationBar虚拟按键栏,ActionBar标题栏)、
* 屏幕宽高以及一些相关的特征。
*/
public static class SystemBarConfig { private static final String STATUS_BAR_HEIGHT_RES_NAME = "status_bar_height";
private static final String NAV_BAR_HEIGHT_RES_NAME = "navigation_bar_height";
private static final String NAV_BAR_HEIGHT_LANDSCAPE_RES_NAME = "navigation_bar_height_landscape";
private static final String NAV_BAR_WIDTH_RES_NAME = "navigation_bar_width";
private static final String SHOW_NAV_BAR_RES_NAME = "config_showNavigationBar"; private final int mStatusBarHeight;
private final int mActionBarHeight;
private final boolean mHasNavigationBar;
private final int mNavigationBarHeight;
private final int mNavigationBarWidth;
private final int mContentHeight;
private final int mContentWidth;
private final boolean mInPortrait;
private final float mSmallestWidthDp; private SystemBarConfig(Activity activity) {
Resources res = activity.getResources();
mInPortrait = (res.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT);
mSmallestWidthDp = getSmallestWidthDp(activity);
mStatusBarHeight = getInternalDimensionSize(res, STATUS_BAR_HEIGHT_RES_NAME);
mActionBarHeight = getActionBarHeight(activity);
mNavigationBarHeight = getNavigationBarHeight(activity);
mNavigationBarWidth = getNavigationBarWidth(activity);
mContentHeight = getContentHeight(activity);
mContentWidth = getContentWidth(activity);
mHasNavigationBar = (mNavigationBarHeight > 0); } // 安卓系统允许修改系统的属性来控制navigation bar的显示和隐藏,此方法用来判断是否有修改过相关属性。
// (修改系统文件,在build.prop最后加入qemu.hw.mainkeys=1即可隐藏navigation bar)
// 相关属性模拟器中有使用。
// 当返回值等于"1"表示隐藏navigation bar,等于"0"表示显示navigation bar。
@TargetApi(19)
private String getNavBarOverride() {
String isNavBarOverride = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
try {
Class c = Class.forName("android.os.SystemProperties");
Method m = c.getDeclaredMethod("get", String.class);
m.setAccessible(true);
isNavBarOverride = (String) m.invoke(null, "qemu.hw.mainkeys");
} catch (Throwable e) {
isNavBarOverride = null;
}
}
return isNavBarOverride;
} //通过此方法获取action bar的高度
@TargetApi(14)
private int getActionBarHeight(Context context) {
int result = 0;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
TypedValue tv = new TypedValue();
context.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true);
result = TypedValue.complexToDimensionPixelSize(tv.data, context.getResources().getDisplayMetrics());
}
return result;
} //通过此方法获取navigation bar的高度
@TargetApi(14)
private int getNavigationBarHeight(Context context) {
Resources res = context.getResources();
int result = 0;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
if (hasNavBar(context)) {
String key;
if (mInPortrait) {
key = NAV_BAR_HEIGHT_RES_NAME;
} else {
key = NAV_BAR_HEIGHT_LANDSCAPE_RES_NAME;
}
return getInternalDimensionSize(res, key);
}
}
return result;
} //通过此方法获取navigation bar的宽度
@TargetApi(14)
private int getNavigationBarWidth(Context context) {
Resources res = context.getResources();
int result = 0;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
if (hasNavBar(context)) {
return getInternalDimensionSize(res, NAV_BAR_WIDTH_RES_NAME);
}
}
return result;
} //通过此方法判断是否存在navigation bar
@TargetApi(14)
private boolean hasNavBar(Context context) {
Resources res = context.getResources();
int resourceId = res.getIdentifier(SHOW_NAV_BAR_RES_NAME, "bool", "android");
if (resourceId != 0) {
boolean hasNav = res.getBoolean(resourceId);
// 查看是否有通过系统属性来控制navigation bar。
if ("1".equals(getNavBarOverride())) {
hasNav = false;
} else if ("0".equals(getNavBarOverride())) {
hasNav = true;
}
return hasNav;
} else {
//可通过此方法来查看设备是否存在物理按键(menu,back,home键)。
return !ViewConfiguration.get(context).hasPermanentMenuKey();
}
} //通过此方法获取资源对应的像素值
private int getInternalDimensionSize(Resources res, String key) {
int result = 0;
int resourceId = res.getIdentifier(key, "dimen", "android");
if (resourceId > 0) {
result = res.getDimensionPixelSize(resourceId);
}
return result;
} //通过此方法获取最小一边的dp值,再通过这个dp值大小来判断设备的navigation bar是显示在底部还是右侧
@TargetApi(17)
private float getSmallestWidthDp(Activity activity) {
DisplayMetrics metrics = new DisplayMetrics();
float widthDp;
float heightDp;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
//API 17之后使用,获取的像素宽高包含虚拟键所占空间,在API 17之前通过反射获取,
//获取的屏幕高度包含status bar和navigation bar
activity.getWindowManager().getDefaultDisplay().getRealMetrics(metrics);
widthDp = metrics.widthPixels / metrics.density;
heightDp = metrics.heightPixels / metrics.density;
} else {
//获取的屏幕高度包含status bar,但不包含navigation bar
activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
widthDp = metrics.widthPixels / metrics.density;
heightDp = (metrics.heightPixels + getNavigationBarWidth(activity))/ metrics.density;
}
return Math.min(widthDp, heightDp);
} //通过此方法获取屏幕高度(不含status bar 和 navigation bar的高度)
private int getContentHeight(Activity activity) {
DisplayMetrics metrics = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
return metrics.heightPixels - getStatusBarHeight();
} //通过此方法获取屏幕的宽度(不含navigation bar的宽度)
private int getContentWidth(Activity activity) {
DisplayMetrics metrics = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
return metrics.widthPixels;
} /**
* 判断navigation bar 是显示在底部还是显示在右侧
*
* @return true表示在底部,false表示在右侧
*/
public boolean isNavigationAtBottom() {
return (mSmallestWidthDp >= 600 || mInPortrait);
} /**
* 获取status bar状态栏高度
*
* @return 状态栏高度的像素值
*/
public int getStatusBarHeight() {
return mStatusBarHeight;
} /**
* 获取action bar的高度
*
* @return action bar高度的像素值
*/
public int getActionBarHeight() {
return mActionBarHeight;
} /**
* 判断此设备是否有navigation bar虚拟按键栏
*
* @return true表示有,false表示无
*/
public boolean hasNavigtionBar() {
return mHasNavigationBar;
} /**
* 获取navigation bar虚拟按键栏的高度
*
* @return 返回navigation bar虚拟按键栏的高度的像素值,如果设备没有navigation bar虚拟按键栏则返回0
*/
public int getNavigationBarHeight() {
return mNavigationBarHeight;
} /**
* 获取navigation bar虚拟按键栏的宽度(当navigation bar虚拟按键栏垂直显示在右侧时使用)
*
* @return 返回navigation bar虚拟按键栏的宽度的像素值,如果设备没有navigation bar虚拟按键栏则返回0
*/
public int getNavigationBarWidth() {
return mNavigationBarWidth;
} /**
* 获取屏幕高度(不含status bar 和 navigation bar的高度)
*
* @return 返回屏幕高度的像素值(不含status bar 和 navigation bar的高度)
*/
public int getContentHeight() {
return mContentHeight;
} /**
* 获取屏幕宽度(不含navigation bar的宽度)
*
* @return 返回屏幕宽度的像素值(不含navigation bar的宽度)
*/
public int getContentWidth() {
return mContentWidth;
} }

二、控制Navigation Bar的显示和隐藏

在Android4.4.2(KITKAT<Build.VERSION_CODES.KITKAT>)之前,只能设置:           
      1)View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
      其缺点是当Touch Screen时,Navigation bar将显示出来。

从Android4.4.2起,可以设置:
      1)View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
      2)View.SYSTEM_UI_FLAG_IMMERSIVE
      同时设置以上两个参数,即使Touch Screen时,Navigation bar也不会显示出来。

实现代码:

 private static Handler sHandler;

 protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); sHandler = new Handler(); sHandler.post(mHideRunnable); // hide the navigation bar final View decorView = getWindow().getDecorView();
decorView
.setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() {
@Override
public void onSystemUiVisibilityChange(int visibility) {
sHandler.post(mHideRunnable); // hide the navigation bar
}
});
} Runnable mHideRunnable = new Runnable() {
@Override
public void run() {
int flags;
int curApiVersion = android.os.Build.VERSION.SDK_INT;
// This work only for android 4.4+
if (curApiVersion >= Build.VERSION_CODES.KITKAT) {
// This work only for android 4.4+
// hide navigation bar permanently in android activity
// touch the screen, the navigation bar will not show
flags = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_IMMERSIVE
| View.SYSTEM_UI_FLAG_FULLSCREEN; } else {
// touch the screen, the navigation bar will show
flags = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
} // must be executed in main thread :)
getWindow().getDecorView().setSystemUiVisibility(flags);
}
};

Android应用:StatusBar状态栏、NavigationBar虚拟按键栏、ActionBar标题栏、Window屏幕内容区域等的宽高的更多相关文章

  1. &lbrack;RK3399&rsqb; 虚拟按键栏显示不全或者方向不对

    CPU:RK3399 系统:Android 7.1 同样的系统代码,换了一个小分辨率的屏,虚拟按键栏就出现显示不全,而且方向不对 出现这种问题的原因是显示密度和屏不匹配,需要适当的降低显示密度即可 d ...

  2. Android设置透明状态栏和透明导航栏

    Android透明状态栏只有在4.4之后有. 在代码中加入下面几行代码即可实现

  3. android 隐藏虚拟按钮栏及标题等权限设置

    华为手机有虚拟按钮,根据以下设置方法可以进行隐藏控制 /** * 隐藏虚拟按键,并且全屏 */ protected void hideBottomUIMenu(Context context){ if ...

  4. GraduateDesign-初试APP编写(去除虚拟按键和禁止状态栏下拉)

    为了毕设的要求,需要在Android系统上运行一个app来控制硬件,今天开始这个app的编写. 首先,我们的系统将只运行这个app,也就是我们不需要状态栏,虚拟按键等. 故这里将app设置为全屏模式. ...

  5. Android 获取虚拟按键的高度

    //获取虚拟按键的高度 public static int getNavigationBarHeight(Context context) { int result = 0; if (hasNavBa ...

  6. Android适配底部虚拟按键的方法

    ---恢复内容开始--- 版权声明:本文为博主原创文章,未经博主允许不得转载. 最近项目进行适配的时候发现部分(如华为手机)存在底部虚拟按键的手机会因为虚拟按键的存在导致挡住部分界面,因为需要全屏显示 ...

  7. Android tp的虚拟按键&lpar;virtual key&rpar;处理

    Android tp的虚拟按键处理 现在在越来越多的Android的手机都是虚拟按键来操作,但是对于开发者来说可能会关心Android对虚拟按键如何处理的.对Linux熟悉的人可能会说,it's ea ...

  8. Android6&period;0 源码修改之屏蔽导航栏虚拟按键(Home和RecentAPP)&sol;动态显示和隐藏NavigationBar

    场景分析, 为了完全实现沉浸式效果,在进入特定的app后可以将导航栏移除,当退出app后再次将导航栏恢复.(下面将采用发送广播的方式来移除和恢复导航栏) ps:不修改源码的情况下,简单的沉浸式效果实现 ...

  9. android适配pad和部分手机底部虚拟按键&plus;沉浸式状态栏

    在使用沉浸式状态栏设置界面全屏时发现pad和部分手机(华为和魅族系统自带)屏幕底部会带有虚拟按键,遮挡住界面本身的一部分. 为了设置隐藏,在网上找了一些方法,设置Activity主题再在布局加fits ...

随机推荐

  1. Scala化规则引擎

    1. 引言 什么是规则引擎 一个业务规则包含一组条件和在此条件下执行的操作,它们表示业务规则应用程序的一段业务逻辑.业务规则通常应该由业务分析人员和策略管理者开发和修改,但有些复杂的业务规则也可以由技 ...

  2. TCP的关闭,到底是几次握手,每次的标志位到底是什么!

    做题的时候遇到一个问题,TCP关闭的时候到底是三次还是四次握手,如果是三次,少了哪部分?   按照 <计算机网络> -第五版-谢希仁       然而对于TCP关闭, 有的地方能找到   ...

  3. 【CodeForces 698A】Vacations

    f[i][0..2]表示第i天休息|运动|比赛最少的休息天数. #include <cstdio> #include <cstring> #include <algori ...

  4. jQ复制按钮的插件zclip

    zclip官网:http://www.steamdev.com/zclip/ swf文件国内下载:ZeroClipboard.swf jQuery-zclip是一个复制内容到剪贴板的jQuery插件, ...

  5. 获取执行计划——EXPLAN PLAN

    一般获取执行计划有四种途径:1.执行explain plan,查询结果输出表.2.查询动态性能视图,它显示缓存在库缓存中的执行计划(有时查不出结果是因为执行计划已经不在库缓存中).3.查询AWR或St ...

  6. const形参与非const形参

    在程序设计中我们会经常调用函数,调用函数就会涉及参数的问题,那么在形参列表中const形参与非const形参对传递过来的实参有什么要求呢? 先来看一个简单的例子: #include <iostr ...

  7. 【转载】PyTorch系列 &lpar;二&rpar;:pytorch数据读取

    原文:https://likewind.top/2019/02/01/Pytorch-dataprocess/ Pytorch系列: PyTorch系列(一) - PyTorch使用总览 PyTorc ...

  8. PythonStudy——PyCharm使用技巧 Column Selection Mode(列选择模式)

    PyCharm的Column Selection Mode提供了列选择功能. 使用: 在当前文件右键->Column Selection Mode->用鼠标垂直选择文本 快捷键:Alt + ...

  9. 【精选】Ubuntu 14&period;04 安装Nginx、php5-fpm、ThinkPHP5&period;0&lpar;已经测试上线&rpar;

    sudo apt-get update 安裝Nginx https://www.vultr.com/docs/setup-nginx-rtmp-on-ubuntu-14-04 安裝完成後,Nginx的 ...

  10. Spring与SpringMVC的关系

    在此鉴于你已经了解过Spring的相关知识,简单描述一下Spring与Spring的关系 在框架的使用中,Spring类似于一个具有多种特性,也可以说是多种功能模块的应用平台,(特性就比如IoC,AO ...