前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Android 屏幕适配】屏幕适配通用解决方案 ③ ( 自定义组件解决方案 | 获取设备状态栏高度 | 获取设备屏幕数据 )

【Android 屏幕适配】屏幕适配通用解决方案 ③ ( 自定义组件解决方案 | 获取设备状态栏高度 | 获取设备屏幕数据 )

作者头像
韩曙亮
发布2023-03-30 16:14:05
9450
发布2023-03-30 16:14:05
举报
文章被收录于专栏:韩曙亮的移动开发专栏

文章目录

参考文档 :

上一篇博客 【Android 屏幕适配】屏幕适配通用解决方案 ② ( 自定义组件解决方案 | 需要解决的问题 : 设计稿坐标数据转为屏幕真实坐标数据 | 实现步骤 ) 中 , 提出 如果要实现将 宽高为 720 x 1232 的设计稿 , 对应 手机屏幕中除 状态栏之外的 布局 , 需要完成如下操作 :

首先 , 要 获取到实际的设备屏幕数据 , 如 手机屏幕实际宽高 , 屏幕像素密度 DPI 等数据 ;

然后 , 计算实际设备的宽高 , 扣掉状态栏的高度 , 不同手机设备状态栏高度不同 , 然后再进行后续计算 ;

再后 , 给出一个 设计稿 与 屏幕实际有效像素值 的 换算比例 ;

最后 , 根据给出的比例 , 在 自定义组件的 onMeasure 方法 中 , 进 行动态换算 , 计算出在当前设备中每个组件的 实际坐标数据 ;

本篇博客中完成前两项工作 ;

一、获取设备状态栏高度


在 com.android.internal.R$dimen.class 字节码类中 , 封装了 设备屏幕尺寸相关属性 , 在这里我们需要获取该字节码类中的 system_bar_height 属性值 ;

首先 , 通过反射获取 com.android.internal.R$dimen 字节码对象 ;

代码语言:javascript
复制
            // 反射 com.android.internal.R$dimen 类
            Class<?> clazz = Class.forName("com.android.internal.R$dimen");

然后 , 调用 Class # newInstance 方法 , 创建 com.android.internal.R$dimen 实例对象 ;

代码语言:javascript
复制
            // 创建 com.android.internal.R$dimen 实例对象
            Object instance = clazz.newInstance();

再后 , 获取上述实例对象的 system_bar_height 字段的值 , 该字段的值是一个 int 类型的 资源 ID ;

代码语言:javascript
复制
            // 获取指定的字段, 这里用于获取 system_bar_height, 也就是系统状态栏高度
            Field field = clazz.getField(systemid);
            // 获取字段的值
            int fieldValue = (int) field.get(instance);

最后 , 调用 Context # getResources().getDimensionPixelOffset 方法 , 将 dimen 类型的资源 ID 转为实际的像素值 ;

代码语言:javascript
复制
            // 获取的字段值是资源 ID, 需要转为实际的像素值
            return context.getResources().getDimensionPixelOffset(fieldValue);

完整代码 :

代码语言:javascript
复制
    /**
     * 通过反射 com.android.internal.R$dimen 类, 获取其中的某些字段
     * @param context   上下文对象
     * @param defValue  如果没有成功获取指定字段, 这里返回一个默认值
     * @return
     */
    public int getDimenValue(Context context, int defValue) {
        try {
            // 反射 com.android.internal.R$dimen 类
            Class<?> clazz = Class.forName("com.android.internal.R$dimen");
            // 创建 com.android.internal.R$dimen 实例对象
            Object instance = clazz.newInstance();
            // 获取指定的字段, 这里用于获取 system_bar_height, 也就是系统状态栏高度
            Field field = clazz.getField("system_bar_height");
            // 获取字段的值
            int fieldValue = (int) field.get(instance);
            // 获取的字段值是资源 ID, 需要转为实际的像素值
            return context.getResources().getDimensionPixelOffset(fieldValue);
        } catch (Exception e) {
            // 如果执行出现异常, 则返回默认值
            return defValue;
        }
    }

二、获取设备屏幕数据


获取设备屏幕数据 :

首先 , 获取 WindowManager 实例对象 , 通过调用 Context # getSystemService(Context.WINDOW_SERVICE) 方法 获取 Android 系统服务进行获取该实例 ;

代码语言:javascript
复制
        // 获取当前设备的屏幕信息
        WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics displayMetrics = new DisplayMetrics();
        windowManager.getDefaultDisplay().getMetrics(displayMetrics);

然后 , 通过 WindowManager 实例获取 DisplayMetrics 示例对象 , 其中封装了设备真实的屏幕数据参数 ; 通过 DisplayMetrics # heightPixels 可以获取屏幕高度 , 通过 DisplayMetrics # widthPixels 可以获取屏幕宽度 ;

代码语言:javascript
复制
        DisplayMetrics displayMetrics = new DisplayMetrics();
        windowManager.getDefaultDisplay().getMetrics(displayMetrics);

再后 , 获取手机状态栏高度 ;

代码语言:javascript
复制
            // 获取状态框高度
            int statusBarHeight = getDimenValue(context,48);

最后 , 处理状态栏信息 , 如果是横屏 , 在宽度方向上减去状态栏高度 , 如果是竖屏 , 在高度上减去状态栏高度 ; 这里通过对比屏幕的宽高来判定当前是横屏还是竖屏 ;

代码语言:javascript
复制
            // 在屏幕真实宽高上减去状态栏高度
            if(displayMetrics.widthPixels > displayMetrics.heightPixels){
                // 宽度大于高度说明是横屏状态, 状态栏在左侧或者右侧
                this.screenWidth = displayMetrics.heightPixels;
                this.screenHeight = displayMetrics.widthPixels - statusBarHeight;
            }else{
                // 高度大于宽度说明是竖屏状态, 状态栏在上侧
                this.screenWidth = displayMetrics.widthPixels;
                this.screenHeight = displayMetrics.heightPixels - statusBarHeight;
            }

完整代码如下 :

代码语言:javascript
复制
    private void initMetrics(){
        // 获取当前设备的屏幕信息
        WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics displayMetrics = new DisplayMetrics();
        windowManager.getDefaultDisplay().getMetrics(displayMetrics);

        if(screenWidth == 0.0f || screenHeight == 0.0f){
            //获取状态框信息
            int statusBarHeight = getDimenValue(context,48);

            // 在屏幕真实宽高上减去状态栏高度
            if(displayMetrics.widthPixels > displayMetrics.heightPixels){
                // 宽度大于高度说明是横屏状态, 状态栏在左侧或者右侧
                this.screenWidth = displayMetrics.heightPixels;
                this.screenHeight = displayMetrics.widthPixels - statusBarHeight;
            }else{
                // 高度大于宽度说明是竖屏状态, 状态栏在上侧
                this.screenWidth = displayMetrics.widthPixels;
                this.screenHeight = displayMetrics.heightPixels - statusBarHeight;
            }
        }
    }
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-08-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 一、获取设备状态栏高度
  • 二、获取设备屏幕数据
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档