zoukankan      html  css  js  c++  java
  • 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.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     }

    如有错误,敬请指正。

  • 相关阅读:
    解决拼团首页swiper组件手动轮播卡顿问题
    mac上charels抓包工具使用技巧
    加载图片优化(先用一张小图片做高斯模糊, 再加载大图)
    requirejs2读书笔记
    escape encodeURI encodeURIComponent区别
    js与cookie的domain和path之间的关系
    Oracle使用——数据泵导入导出数据库——impdp/expdp使用
    Oracle基础知识点——Oracle服务端和客户端
    Oracle使用——oracle11g安装——Oracle要求的结果: 5.0,5.1,5.2,6.0 6.1 之一 实际结果: 6.2
    Spring 学习——Spring AOP——AOP配置篇Advice(有参数传递)
  • 原文地址:https://www.cnblogs.com/xilinch/p/4444833.html
Copyright © 2011-2022 走看看