Android获取状态栏高度、标题栏高度、编辑区域高度的获取

文章转自:http://blog.csdn.net/a_running_wolf/article/details/50477965

日常开发中我们经常会因为绘图、绘制自定义组件、定位组件或者是计算布局高度需要减去状态栏高度等需要来获取Activity界面中状态栏、标题栏的高度。但很多人马上要拿起来就用还是会遇到各种各样的问题,一时要查很多资料,很是不爽!今天也是猛然发现这个问题费了不少时间,终于有所收获,特地记录下来,希望给遇到同样问题的你一点帮助,也给以后留个笔记。废话少说,开始正题吧——

一、Activity界面区域划分

先上一张图统一一下认识,有图好说话:
这里写图片描述

简单说明一下(上图Activity采用默认Style,状态栏和标题栏都会显示):最大的草绿色区域是屏幕界面,红色次大区域我们称之为“应用界面区域”,最小紫色的区域我们称之为“View绘制区域”;屏幕顶端、应用界面区之外的那部分显示手机电池网络运营商信息的为“状态栏”,应用区域顶端、View绘制区外部显示Activity名称的部分我们称为“标题栏”。

二、状态高度的测量

状态栏是显示显示手机状态(如电池电量、网络状态、时间、运营商信息等)的区域,一般内容型应用都会显示保留状态栏,但是游戏界面如果还保留状态栏就不合适了,因为游戏界面要响应各种手势,而状态栏也会响应一些手势,有可能引发错误操作,所以一般在游戏界面都会隐藏状态栏,使游戏界面全屏显示,关于设置全屏请查看《Android设置Activity全屏的两种方式及Theme属性解析》,继续看状态栏高度测量:

状态栏高度的测量我在这里提供4种方法:

(1)通过系统尺寸资源获取

状态栏高度定义在Android系统尺寸资源中status_bar_height,但这并不是公开可直接使用的,例如像通常使用系统资源那样android.R.dimen.status_bar_height。但是系统给我们提供了一个Resource类,通过这个类可以获取资源文件,借此可以获取到status_bar_height:

 /** 
 * 获取状态栏高度——方法1 
 * */  
int statusBarHeight1 = -1;  
//获取status_bar_height资源的ID  
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");  
if (resourceId > 0) {  
    //根据资源ID获取响应的尺寸值  
    statusBarHeight1 = getResources().getDimensionPixelSize(resourceId);  
}  
Log.e("WangJ", "状态栏-方法1:" + statusBarHeight1);  

这里写图片描述

(2)通过R类的反射

大家都知道Android的所有资源都会有惟一标识在R类中作为引用。我们也可以通过反射获取R类的实例域,然后找status_bar_height:

/** 
* 获取状态栏高度——方法2 
* */  
int statusBarHeight2 = -1;  
try {  
    Class<?> clazz = Class.forName("com.android.internal.R$dimen");  
    Object object = clazz.newInstance();  
    int height = Integer.parseInt(clazz.getField("status_bar_height").get(object).toString());  
    statusBarHeight2 = getResources().getDimensionPixelSize(height);  
} catch (Exception e) {  
     e.printStackTrace();  
}  
Log.e("WangJ", "状态栏-方法2:" + statusBarHeight2);

这里写图片描述

(3)借助应用区域的top属性

这就用到了开题时的那张屏幕区域划分图片,状态栏位于屏幕最顶端,其位置从(0,0)开始,故而应用区域的顶端位置(高度 = Y坐标 - 0)即为状态栏的高度:

/** 
* 获取状态栏高度——方法3 
* 应用区的顶端位置即状态栏的高度 
* *注意*该方法不能在初始化的时候用 
* */  
Rect rectangle= new Rect();  
getWindow().getDecorView().getWindowVisibleDisplayFrame(rectangle);  
//高度为rectangle.top-0仍为rectangle.top  
Log.e("WangJ", "状态栏-方法3:" + rectangle.top); 

这里写图片描述

注意: 如果单单获取statusBar高度而不获取titleBar高度时,这种方法并不推荐大家使用,因为这种方法依赖于WMS(窗口管理服务的回调)。正是因为窗口回调机制,所以在Activity初始化时执行此方法得到的高度是0,这就是很多人获取到statusBar高度为0的原因。这个方法推荐在回调方法onWindowFocusChanged()中执行,才能得到预期结果。

(4)借助屏幕和应用区域高度

还是看屏幕区域划分图,是不是状态栏占满了屏幕中除应用区域之外的全部呢?所以直接上代码:

/** 
* 获取状态栏高度——方法4 
* 状态栏高度 = 屏幕高度 - 应用区高度 
* *注意*该方法不能在初始化的时候用 
* */  
//屏幕  
DisplayMetrics dm = new DisplayMetrics();  
getWindowManager().getDefaultDisplay().getMetrics(dm);  
//应用区域  
Rect outRect1 = new Rect();  
getWindow().getDecorView().getWindowVisibleDisplayFrame(outRect1);  
int statusBar = dm.heightPixels - outRect1.height();  //状态栏高度=屏幕高度-应用区域高度  
Log.e("WangJ", "状态栏-方法4:" + statusBar);

这里写图片描述

三、标题栏高度的测量

搞懂了上边的原理,标题栏高度的测量也就手到擒来啦,依旧是屏幕区域划分图。这里也给出两种方法,先给出公共代码吧,就是获取各区域(注意 : 依旧是在Activity的回调方法onWindowFocusChanged()中执行,才能得到预期结果):

//屏幕  
DisplayMetrics dm = new DisplayMetrics();  
getWindowManager().getDefaultDisplay().getMetrics(dm);  
Log.e("WangJ", "屏幕高:" + dm.heightPixels);  

//应用区域  
Rect outRect1 = new Rect();  
getWindow().getDecorView().getWindowVisibleDisplayFrame(outRect1);  
Log.e("WangJ", "应用区顶部" + outRect1.top);  
Log.e("WangJ", "应用区高" + outRect1.height());  

//View绘制区域  
Rect outRect2 = new Rect();  
getWindow().findViewById(Window.ID_ANDROID_CONTENT).getDrawingRect(outRect2);   
Log.e("WangJ", "View绘制区域顶部-错误方法:" + outRect2.top);//不能像上边一样由outRect2.top获取,这种方式获得的top是0,可能是bug吧  
int viewTop = getWindow().findViewById(Window.ID_ANDROID_CONTENT).getTop();//要用这种方法  
Log.e("WangJ", "View绘制区域顶部-正确方法:" + viewTop);  
Log.e("WangJ", "View绘制区域高度:" + outRect2.height());

这里写图片描述

以手到擒来了吧,有没有遇到获取View绘制区时列出来的那个outRect2.top=0的问题呢?原因我们还没搞懂呢,哪位大侠搞懂了留言给个贡献值啊,求教了!

(1)top-top

直接看代码,文笔不好(其实是懒得写字):

/** 
* 获取标题栏高度-方法1 
* 标题栏高度 = View绘制区顶端位置 - 应用区顶端位置(也可以是状态栏高度,获取状态栏高度方法3中说过了) 
* */  
int titleHeight1 = viewTop - outRect1.top;  
Log.e("WangJ", "标题栏高度-方法1:" + titleHeight1); 

这里写图片描述

(2)高度-高度

还是看代码,有注释:

/** 
* 获取标题栏高度-方法2 
* 标题栏高度 = 应用区高度 - View绘制区高度 
* */  
int titleHeight2 = outRect1.height() - outRect2.height();  
Log.e("WangJ", "标题栏高度-方法2:" + titleHeight2);

这里写图片描述

四、注意事项

(1)不管你是否设置全屏模式,或是不显示标题栏,在使用获取状态栏高度方法1获取状态栏高度方法2都会测量到状态栏的高度,理解原理就不难解释——系统资源属性是固定的、真实的,不管你是否隐瞒(隐藏或者显示),它都在那里;

(2)但是若使用获取状态栏高度方法3获取状态栏高度方法4,以及获取标题栏高度方法1获取标题栏高度方法2,都是依赖于WMS,是在界面构建后根据View获取的,所以显示了就有高度,不显示自然没高度了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值