TypedValue.applyDimension 中dp和sp之间转化的真相

简介: 最近在看了许多关于dp-px,px-dp,sp-px,px-sp之间转化的博文,过去我比较常用的方式是: 1 //转换dip为px 2 public static int convertDipOrPx(Context context, int dip) { 3 float scale = context.

   最近在看了许多关于dp-px,px-dp,sp-px,px-sp之间转化的博文,过去我比较常用的方式是:

 1 //转换dip为px 
 2 public static int convertDipOrPx(Context context, int dip) { 
 3     float scale = context.getResources().getDisplayMetrics().density; 
 4     return (int)(dip*scale + 0.5f*(dip>=0?1:-1)); 
 5 } 
 6  
 7 //转换px为dip 
 8 public static int convertPxOrDip(Context context, int px) { 
 9     float scale = context.getResources().getDisplayMetrics().density; 
10     return (int)(px/scale + 0.5f*(px>=0?1:-1)); 
11 } 

然后看到了一种新的转化方式,代码如下:

1 public static int dp2sp(float dpVal){
2     return (int)(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpVal,
3             MyAppliction.getInstance().getApplicationContext().getResources().getDisplayMetrics()));
4 }
5  //?????
6 public static int sp2dp(float spVal){
7     return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, spVal,
8             MyAppliction.getInstance().getApplicationContext().getResources().getDisplayMetrics()));
9 }

码农对TypedValue充满好奇,通过查询官网了解该类

TypedValue

  ---android.util.TypedValue
 
Container for a dynamically typed data value. Primarily used with Resources for holding resource values.

 翻译过来就是:这个类是工具类,作为一个动态容器,它存放一些数据值,这些值主要是resource中的值。

我们来理解一下:resource中到底有哪些值?layout、drawable、string、style、anim、dimens、menu、colors、ids这些值一些和屏幕适配有直接的关系。

有一些方法必然是可以读取这些资源文件信息的,比如:

getDimension(DisplayMetrics metrics)

再看具体的方法:

applyDimension(int unit, float value,DisplayMetrics metrics)
第一个参数是单位,第二个参数是对应值,第三个你懂的,封装了显示区域的各种属性值。

对于applyDimension(int unit, float value,DisplayMetrics metrics)中的代码我们来看下

 1  public static float applyDimension(int unit, float value,
 2                                        DisplayMetrics metrics)
 3     {
 4         switch (unit) {
 5         case COMPLEX_UNIT_PX:
 6             return value;
 7         case COMPLEX_UNIT_DIP:
 8             return value * metrics.density;
 9         case COMPLEX_UNIT_SP:
10             return value * metrics.scaledDensity;
11         case COMPLEX_UNIT_PT:
12             return value * metrics.xdpi * (1.0f/72);
13         case COMPLEX_UNIT_IN:
14             return value * metrics.xdpi;
15         case COMPLEX_UNIT_MM:
16             return value * metrics.xdpi * (1.0f/25.4f);
17         }
18         return 0;
19     }

其中单位为dip的,将其转化为密度*值,也就是像素值,而单位sp的也将其转化为px值,因此该方法可以能进行

dip-->px

sp-- >px

因此上面

TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, value ,DisplayMetrics );
这个方法肯定不能将sp转化为dp,我们判断

dp2sp(50) = 150

sp2dp(50) = 150

convertDipOrPx(50) = 150

convertPxOrDip(50) = 17
将代码运行实际结果与判断结果一致。

接下来我们继续分析

TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, value ,DisplayMetrics );
该方法系统本意是用来做什么的?

查看官方说明:

Converts an unpacked complex data value holding a dimension to its final floating point value.

这里就把对应的值转化为实际屏幕上的点值,也就是像素值。
如果是TypedValue.COMPLEX_UNIT_DIP,则乘以显示密度density。

而如果是TypedValue.COMPLEX_UNIT_SP,则乘以像素密度scaledDensity

 

我们继续刨根追底

density和scaledDensity的区别在于

density:The logical density of the display.显示密度density = dpi/160

scaledDensity:A scaling factor for fonts displayed on the display.显示字体的缩放因子 = density

实际上两者的值一样,为了验证这个结论我们随便找两台机器小米2S和华为p7,取出density和scaledDensity是一致的,P7为3.0,小米2S = 2.0

 

因此本文结论转化dp-px,px-dp,sp-px,px-sp

使用下面方法:

 1 //转换dip为px 
 2   public static int convertDipOrPx(Context context, int dip) { 
 3       float scale = context.getResources().getDisplayMetrics().density; 
 4       return (int)(dip*scale + 0.5f*(dip>=0?1:-1)); 
 5   } 
 6    
 7   //转换px为dip 
 8   public static int convertPxOrDip(Context context, int px) { 
 9       float scale = context.getResources().getDisplayMetrics().density; 
10      return (int)(px/scale + 0.5f*(px>=0?1:-1)); 
11  } 
12  
13   public static int sp2px(Context context, float spValue) {
14         float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
15         return (int) (spValue * fontScale + 0.5f);
16     }
17 
18     public static int px2sp(Context context, float pxValue) {
19         float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
20         return (int) (pxValue / fontScale + 0.5f);
21     }

 

如有错误,敬请指正。

 

目录
相关文章
EMQ
|
安全 网络性能优化
MQTT 5.0 报文(Packets)入门指南
MQTT 控制报文是 MQTT 数据传输的最小单元。MQTT 客户端和服务端通过交换控制报文来完成它们的工作,比如订阅主题和发布消息。
EMQ
1094 96
MQTT 5.0 报文(Packets)入门指南
|
11月前
|
前端开发 微服务
开发指南056-定时任务
业务场景中定时任务很常见。平台实现定时任务的原则如下
|
弹性计算 运维 安全
阿里云无影云电脑详细介绍_使用_价格_优势_功能_特性
什么是阿里云无影云电脑?无影云电脑(原云桌面)是一种快速构建、高效管理桌面办公环境,无影云电脑可用于远程办公、多分支机构、安全OA、短期使用、专业制图等使用场景,阿里云百科分享无影云桌面的详细介绍、租用价格、云电脑的优势、使用场景、网络架构、无影云电脑与云服务器的区别以及关于无影云电脑的常见问题解答FAQ
893 0
|
安全 Java 程序员
火爆全网的Spring Security手册及源码笔记,在Github上标星103K
Spring Security 是一个基于 Spring AOP 和 Servlet 过滤器的安全框架,它提供了安全性方面的解决方案 Spring Security作为非常强大的框架,作为程序员是非常热爱的,我这里整理了四份Spring Security手写笔记及实战手册分享给大家
|
Cloud Native 测试技术 领域建模
领域模型为核心的架构设计 初篇
领域模型为核心的架构设计 初篇
384 0
领域模型为核心的架构设计 初篇
|
C# 图形学
Unity C#基础之 特性,一个灵活的小工具
特性在框架中的应用也是很普遍,只需要在相应的类、字段、属性、函数等上面加上这个特殊的小东西就会在相应的元素上面添加一些特殊的应用效果,下面就为大家简单的介绍下特性的原理和应用场景 在往期的博客中有介绍过一些特性 Unity Debug输出到屏幕并保存到本地中的Conditional("EnableLog")特性 Unity Attributes中Unity自带的特性 Obsolete、Serializable等 下面咱们来聊一聊特性到底是个什么,都能干什么?为什么说它是一个灵活的小工具。
1989 0
|
2天前
|
存储 关系型数据库 分布式数据库
PostgreSQL 18 发布,快来 PolarDB 尝鲜!
PostgreSQL 18 发布,PolarDB for PostgreSQL 全面兼容。新版本支持异步I/O、UUIDv7、虚拟生成列、逻辑复制增强及OAuth认证,显著提升性能与安全。PolarDB-PG 18 支持存算分离架构,融合海量弹性存储与极致计算性能,搭配丰富插件生态,为企业提供高效、稳定、灵活的云数据库解决方案,助力企业数字化转型如虎添翼!
|
13天前
|
弹性计算 关系型数据库 微服务
基于 Docker 与 Kubernetes(K3s)的微服务:阿里云生产环境扩容实践
在微服务架构中,如何实现“稳定扩容”与“成本可控”是企业面临的核心挑战。本文结合 Python FastAPI 微服务实战,详解如何基于阿里云基础设施,利用 Docker 封装服务、K3s 实现容器编排,构建生产级微服务架构。内容涵盖容器构建、集群部署、自动扩缩容、可观测性等关键环节,适配阿里云资源特性与服务生态,助力企业打造低成本、高可靠、易扩展的微服务解决方案。
1281 5