博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【android】getDimension()、getDimensionPixelOffset()和getDimensionPixelSize()区别详解
阅读量:5900 次
发布时间:2019-06-19

本文共 2962 字,大约阅读时间需要 9 分钟。

在自定义控件中使用自定义属性时,经常需要使用java代码获取在xml中定义的尺寸,相关有以下三个函数

 

  • getDimension()
  • getDimensionPixelOffset()
  • getDimensionPixelSize()

(在类TypedArray和类Resources中都有这三个函数,功能类似,TypedArray中的函数是获取自定义属性的,Resources中的函数是获取android预置属性的)

通常初学者(尤其是洋文不大好的朋友们)看到这三个函数的名称时会有点不知所云。反正在我仔细研究前是这样,getDimensionPixelSize()函数看名称是获取像素,那getDimensionPixelOffset()这玩意儿的offset是啥(通常API里不都是 begin, offset, len么)?  getDimension()这个函数又是干啥的,和getDimensionPixelSize()有什么区别吗,是获取原始的dp值吗(答案是否定的)?

       高手请无视本帖,不太明白的初学者可以往下仔细看看哦~

带着这些疑惑,看看API reference里的解释:

 

  • getDimension()是基于当前DisplayMetrics进行转换,获取指定资源id对应的尺寸。文档里并没说这里返回的就是像素,要注意这个函数的返回值是float,像素肯定是int。
  • getDimensionPixelSize()与getDimension()功能类似,不同的是将结果转换为int,并且小数部分四舍五入。
  • getDimensionPixelOffset()与getDimension()功能类似,不同的是将结果转换为int,并且偏移转换(offset conversion,函数命名中的offset是这个意思)是直接截断小数位,即取整(其实就是把float强制转化为int,注意不是四舍五入哦)。

 

由此可见,这三个函数返回的都是绝对尺寸,而不是相对尺寸(dp/sp等)。如果getDimension()返回结果是20.5f,那么getDimensionPixelSize()返回结果就是21,getDimensionPixelOffset()返回结果就是20。

到这里本帖就可以结束了,但如果想知道的多一点,还可以看看android的源代码,来印证上述解释。

 

深入源码,我们可以发现其实这三个函数实现都很像,以Resources类的getDimension()为例

 

 

public float getDimension(int id) throws NotFoundException {        synchronized (mTmpValue) {            TypedValue value = mTmpValue;            getValue(id, value, true);            if (value.type == TypedValue.TYPE_DIMENSION) {                return TypedValue.complexToDimension(value.data, mMetrics);            }            throw new NotFoundException(                    "Resource ID #0x" + Integer.toHexString(id) + " type #0x"                    + Integer.toHexString(value.type) + " is not valid");        }    }

类TypedValue是动态类型数据的容器,主要用于盛放resource的值。上述代码第4行就是根据resId获取TypedValue的值,getDimension()、getDimensionPixelOffset()和getDimensionPixelSize()函数体唯一的不同就是第4行:

  • getDimension()调用的是TypedValue的complexToDimension方法
  • getDimensionPixelSize调用的是TypedValue的complexToDimensionPixelSize方法
  • getDimensionPixelOffset调用的是TypedValue的complexToDimensionPixelOffset方法

我们再深入类TypedValue,查看complexToDimension()、complexToDimensionPixelSize()和complexToDimensionPixelOffset()函数的区别,会发现这三个函数体内容还是差不多,以complexToDimension()为例:

 

public static float complexToDimension(int data, DisplayMetrics metrics)    {        return applyDimension(            (data>>COMPLEX_UNIT_SHIFT)&COMPLEX_UNIT_MASK,            complexToFloat(data),            metrics);    }

complexToDimensionPixelOffset()与complexToDimension()不同的是将结果进行了强制转换,相当于直接截断小数部分;

complexToDimensionPixelSize()是将结果进行四舍五入,四舍五入的代码就是把结果加上0.5f再进行强制转换(因为java的float强制转换为int都是直接舍去小数的;如果大于等于0.5则加上0.5进位,强制转换后舍去小数相当于五入;如果小于0.5则加上0.5后整数部分不变,强制转换舍去小数后相当于四舍,java基础,第一次接触的新手普及下~)

 

ok了,简单的源码分析完成了。 通过源码分析,进一步验证了getDimension()、getDimensionPixelOffset()和getDimensionPixelSize()的区别,大家以后再用到这三个函数的时候就不用发蒙了。在java代码里很多setWidth(),setHeight()的参数都是像素,即整形,大家根据实际情况,看看如果是四舍五入就调用getDimensionPixelSize(),如果是取整就调用getDimensionPixelOffset()。千万不要setWidth((int)getDimension()) 这么写哦!

后记: android并没有在java代码中直接获取xml中定义的dp/sp的值的API,可能是因为google认为没有必要。但如果实在想得到xml中咱们自己写的dp或sp的值(例如想在日志里输出dp/sp什么的),请参见我的另一个帖子Java代码获取xml中定义的dp/sp值的方法

 

转载地址:http://lyesx.baihongyu.com/

你可能感兴趣的文章
STS中db.properties配置文件
查看>>
Hibernate事务代码规范写法
查看>>
网络最大流问题算法小结 [转]
查看>>
程序员英语轻松学1
查看>>
面试之Java知识整理
查看>>
Convert.ToInt32(),Int.Parse(),Int.TryParse()的区别
查看>>
基于udp的scoket通信
查看>>
(转载)屌丝从毕业时的月入3000到三年后亿万身家的精彩励志之旅
查看>>
大白话5分钟带你走进人工智能-目录
查看>>
iOS推送消息报错误“Domain=NSCocoaErrorDomain Code=3000”的可能问题
查看>>
JavaScript获取页面宽高度的方法
查看>>
找不到方法:“Boolean System.Runtime.Serialization.DataContractAttribute.get_IsReference()”
查看>>
eclipse启动时提示"Failed to load the jni shared library"
查看>>
Android开发指南(30) —— Multimedia and Camera
查看>>
kvm-1
查看>>
Jmeter的接口测试简介
查看>>
第二阶段冲刺03
查看>>
hdu1045 Fire Net---二进制枚举子集
查看>>
drupal网站邮件发送功能的实现
查看>>
leetcode 64. Minimum Path Sum
查看>>