在自定义控件中使用自定义属性时,经常需要使用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值的方法

【android】getDimension()、getDimensionPixelOffset()和getDimensionPixelSize()区别详解的更多相关文章

  1. android: getDimension, getDimensionPixelOffset 和getDimensionPixelSize 区别

    ◆结论: getDimension 获取某个dimen的值,如果是dp或sp的单位,将其乘以density,如果是px,则不乘   返回float getDimensionPixelOffset 获取 ...

  2. getDimension()、getDimensionPixelOffset()和getDimensionPixelSize()区别详解

    getDimension()是基于当前DisplayMetrics进行转换,获取指定资源id对应的尺寸.文档里并没说这里返回的就是像素,要注意这个函数的返回值是float,像素肯定是int. getD ...

  3. Android中getDimension,getDimensionPixelOffset和getDimensionPixelSize 区别

    getDimension 获取某个dimen的值,如果是dp或sp的单位,将其乘以density,如果是px,则不乘   返回float getDimensionPixelOffset 获取某个dim ...

  4. Android中Intent传值与Bundle传值的区别详解

    Android中Intent传值与Bundle传值的区别详解 举个例子我现在要从A界面跳转到B界面或者C界面   这样的话 我就需要写2个Intent如果你还要涉及的传值的话 你的Intent就要写两 ...

  5. SurfaceView 与view区别详解

    SurfaceView 与view区别详解 https://blog.csdn.net/u011339364/article/details/83347109 2018年10月24日 17:20:08 ...

  6. 基于Java的打包jar、war、ear包的作用与区别详解

      本篇文章,小编为大家介绍,基于Java的打包jar.war.ear包的作用与区别详解.需要的朋友参考下   以最终客户的角度来看,JAR文件就是一种封装,他们不需要知道jar文件中有多少个.cla ...

  7. php 去除html标记--strip_tags与htmlspecialchars的区别详解

    php 去除html标记--strip_tags与htmlspecialchars的区别详解 作者: 字体:[增加 减小] 类型:转载 时间:2013-06-26   本篇文章是对php中去除html ...

  8. HTTP POST GET 本质区别详解

    HTTP POST GET 本质区别详解 一 原理区别 一般在浏览器中输入网址访问资源都是通过GET方式:在FORM提交中,可以通过Method指定提交方式为GET或者POST,默认为GET提交 Ht ...

  9. javascript中=、==、===区别详解

    javascript中=.==.===区别详解今天在项目开发过中发现在一个小问题.在判断n==""结果当n=0时 n==""结果也返回了true.虽然是个小问题 ...

随机推荐

  1. LA 4094 WonderTeam 构造

    题意: 一共有\(n\)支队伍参加比赛,每两支队伍比赛两场,主客场各一场. 胜场得\(3\)分,平局得1分,败场不得分. 一支得分为\(p\)的队伍的排名\(=\)分数大于\(p\)的队伍数\(+1\ ...

  2. 修改DB-LINK连接数方法

    原因分析有可能是DB-LINK连接数的限制,请做如下修改验证: 以oracle用户登录数据库节点. 连接数据库. $ sqlplus "/as sysdba"修改DataBase ...

  3. day03_13 多分支if语句及作业

    猜年龄升级版 age_of_princal = 56 guess_age = int( input("请输入您猜测的年龄") ) if guess_age == age_of_pr ...

  4. Deep Android Malware Detection小结

    题目:Deep Android Malware Detection 作者:Niall McLaughlin, Jesus Martinez del Rincon, BooJoong Kang 年份:2 ...

  5. hdu1595 最短路问题(dijkstra&&spfa)

    find the longest of the shortest Time Limit: 1000/5000 MS (Java/Others)    Memory Limit: 32768/32768 ...

  6. Hibernate框架简述(转)

    转自:http://www.cnblogs.com/eflylab/archive/2007/01/09/615338.html Hibernate的核心组件在基于MVC设计模式的JAVA WEB应用 ...

  7. div固定在屏幕底部

    项目中需要实现div一直显示在屏幕的底部,不管页面有多长或者多端都需要满足. 在网上找的用js实现的,移动时会闪动,效果不是特别好.也可能是没找到好的. 相比js,我更希望使用css实现 1 < ...

  8. POJ——1195Mobile phones(二维树状数组点修改矩阵查询)

    Mobile phones Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 17764   Accepted: 8213 De ...

  9. [LOJ#531]「LibreOJ β Round #5」游戏

    [LOJ#531]「LibreOJ β Round #5」游戏 试题描述 LCR 三分钟就解决了问题,她自信地输入了结果-- > -- 正在检查程序 -- > -- 检查通过,正在评估智商 ...

  10. 刷题总结——影魔(HNOI2017 BZOJ4826 线段树+扫描线)

    题目: Description 影魔,奈文摩尔,据说有着一个诗人的灵魂.事实上,他吞噬的诗人灵魂早已成千上万.千百年来,他收集了各式各样 的灵魂,包括诗人.牧师.帝王.乞丐.奴隶.罪人,当然,还有英雄 ...