完美获取Android状态栏高度

本文介绍了一种有效的方法来获取Android设备的状态栏高度,解决了在应用开发中遇到的一个常见问题。通过反射机制调用特定API,确保了获取的高度准确无误。

来自: http://www.cnblogs.com/LuoYer/archive/2011/11/06/2238167.html

闲暇写了个单本小说阅读的应用。中间碰到了需要获取状态栏高度的问题。

就像android后期版本,无法直接退出一样。找了一些方法来获取状态栏高度,结果都是为0.

还好,牛人是很多的,当时,找到一段代码,能够有效的获取状态栏的高度。特此记录,备忘,以及供大家参考。

Class<?> c = null ;
Object obj = null ;
Field field = null ;
int x = 0 , sbar = 0 ;
try {
    c = Class.forName( "com.android.internal.R$dimen" );
    obj = c.newInstance();
    field = c.getField( "status_bar_height" );
    x = Integer.parseInt(field.get(obj).toString());
    sbar = getResources().getDimensionPixelSize(x);
} catch (Exception e1) {
    loge( "get status bar height fail" );
    e1.printStackTrace();
}

个人注:以下代码不能在onCreate里面使用,否则获取状态栏高度为0

Rect frame = new Rect();

getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);

int statusBarHeight = frame.top;

 

 

<think> 根据用户当前的问题,用户希望了解在安卓开发中获取状态栏高度的方法。结合用户提供的历史引用(引用[1]到引用[4])以及之前对话中关于状态栏显示/隐藏的讨论,我将整理几种获取状态栏高度的方法,并给出兼容性建议。 ### 核心方法总结 #### 方法1:通过资源ID获取(推荐) ```java public static int getStatusBarHeight(Context context) { int result = 0; int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android"); if (resourceId > 0) { result = context.getResources().getDimensionPixelSize(resourceId); } return result; } ``` > ✅ 优点:官方推荐,无需反射 > ⚠️ 注意:在部分定制ROM可能返回0,需兼容处理[^1][^3] #### 方法2:使用反射获取(备用方案) ```java public static int getStatusBarHeightByReflection(Context context) { try { Class<?> clazz = Class.forName("com.android.internal.R$dimen"); Object obj = clazz.newInstance(); Field field = clazz.getField("status_bar_height"); int id = Integer.parseInt(field.get(obj).toString()); return context.getResources().getDimensionPixelSize(id); } catch (Exception e) { e.printStackTrace(); return 0; // 失败时返回0或使用其他方法 } } ``` > ⚠️ 警告:反射存在性能开销和兼容性风险[^4] --- ### 高级场景处理 #### 1. 实时获取状态栏高度 ```java View decorView = getWindow().getDecorView(); Rect rect = new Rect(); decorView.getWindowVisibleDisplayFrame(rect); int statusBarHeight = rect.top; // 直接获取状态栏高度 ``` > 💡 适用于动态布局调整,能实时反映状态栏变化[^2] #### 2. 兼容全面屏/挖孔屏 ```java // 在Activity的onCreate中 ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> { int statusBarHeight = insets.getInsets(WindowInsetsCompat.Type.statusBars()).top; // 使用获取高度调整布局 return insets; }); ``` > 要求:Android 5.0+,使用`androidx.core:core`库 > ✅ 最佳实践:完美适配异形屏[^2] --- ### 使用注意事项 1. **调用时机**:在`onWindowFocusChanged()`中获取可避免高度0 ```java public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); if (hasFocus) { int height = getStatusBarHeight(this); // 更新布局 } } ``` 2. **单位转换**:`getDimensionPixelSize`返回像素值,需根据设计稿适配 ```java // 转换为dp(可选) float dpHeight = TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, height, getResources().getDisplayMetrics() ); ``` 3. **全面屏适配**:部分设备状态栏高度可能异常,建议设置最小阈值 ```java if (height <= 0) { height = (int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, 24, // 默认24dp getResources().getDisplayMetrics() ); } ``` --- ### 完整工具类封装 ```java public class StatusBarUtils { /** * 获取状态栏高度(像素) * @param context 上下文 * @return 高度值,失败返回0 */ public static int getHeight(@NonNull Context context) { // 方法1:资源ID获取 int resourceId = context.getResources() .getIdentifier("status_bar_height", "dimen", "android"); if (resourceId > 0) { return context.getResources().getDimensionPixelSize(resourceId); } // 方法2:反射获取 try { Class<?> clazz = Class.forName("com.android.internal.R$dimen"); Field field = clazz.getField("status_bar_height"); int id = Integer.parseInt(field.get(clazz.newInstance()).toString()); return context.getResources().getDimensionPixelSize(id); } catch (Exception e) { // 忽略异常 } // 方法3:实时计算(需要Activity环境) if (context instanceof Activity) { Rect rect = new Rect(); ((Activity) context).getWindow().getDecorView() .getWindowVisibleDisplayFrame(rect); return rect.top; } return 0; } } ``` §§相关问题§§ 1. 如何正确适配Android全面屏的状态栏? 2. 获取状态栏高度返回0的可能原因有哪些? 3. 如何在Fragment中安全获取状态栏高度? 4. 动态改变状态栏颜色后如何同步更新高度? </think> ### Android 获取状态栏高度的完整指南 在Android开发中,动态获取状态栏高度是常见需求,特别是在处理沉浸式布局时。以下是几种可靠的方法: #### 方法1:通过系统资源获取(推荐) ```java public static int getStatusBarHeight(Context context) { int result = 0; // 获取系统资源标识符 int resourceId = context.getResources().getIdentifier( "status_bar_height", "dimen", "android" ); // 验证资源是否存在 if (resourceId > 0) { // 返回像素尺寸值 result = context.getResources().getDimensionPixelSize(resourceId); } return result; } ``` > ✅ **优点**:官方推荐方法,无需反射 > ⚠️ **注意**:在`onCreate()`中调用可能返回0,建议在`onWindowFocusChanged()`中使用[^1][^3] --- #### 方法2:使用反射获取(备选方案) ```java public static int getStatusBarHeightByReflection(Context context) { try { // 反射获取系统内部类 Class<?> clazz = Class.forName("com.android.internal.R$dimen"); Object obj = clazz.newInstance(); Field field = clazz.getField("status_bar_height"); // 获取资源ID值 int id = Integer.parseInt(field.get(obj).toString()); return context.getResources().getDimensionPixelSize(id); } catch (Exception e) { e.printStackTrace(); return 0; // 失败时返回默认值 } } ``` > ⚠️ **注意**:反射存在兼容性风险,仅在必要情况下使用[^4] --- #### 方法3:实时获取可见区域高度 ```java // 在Activity中使用 View decorView = getWindow().getDecorView(); Rect rect = new Rect(); decorView.getWindowVisibleDisplayFrame(rect); int statusBarHeight = rect.top; ``` > ✅ **适用场景**:当状态栏动态显示/隐藏时获取实时高度[^2] --- ### 使用示例 ```java // 在Activity中调用 @Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); if (hasFocus) { int statusBarHeight = getStatusBarHeight(this); Log.d("StatusBar", "Height: " + statusBarHeight + "px"); // 调整布局避免遮挡 View contentView = findViewById(R.id.content); contentView.setPadding(0, statusBarHeight, 0, 0); } } ``` ### 注意事项 1. **单位转换**:获取的是像素值,如需dp单位需转换: ```java float dpHeight = statusBarHeight / getResources().getDisplayMetrics().density; ``` 2. **全面屏适配**:异形屏状态栏高度可能不同,建议使用`WindowInsetsCompat`: ```java ViewCompat.setOnApplyWindowInsetsListener(view, (v, insets) -> { int top = insets.getSystemWindowInsetTop(); // 使用top值 return insets; }); ``` 3. **兼容性处理**:添加默认值保护 ```java if (statusBarHeight == 0) { statusBarHeight = (int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, 24, // 默认24dp getResources().getDisplayMetrics() ); } ``` ---
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值