getResources().getDimension(R.dimen.xsmall_text_size) 与 setTextSize(16)区别

转载

http://blog.csdn.net/philofly/article/details/8652439


由sp单位引发的惨案

分类: android 699人阅读 评论(0) 收藏 举报

我的一个同事自定义了一个控件,控件代码如下:

 

[java] view plain copy
  1. public class CustomTextView extends TextView implements OnClickListener,  
  2.         OnFocusChangeListener {  
  3.   
  4.     public CustomTextView(Context context) {  
  5.         super(context);  
  6.         init(context);  
  7.     }  
  8.   
  9.     public CustomTextView(Context context, AttributeSet attrs, int defStyle) {  
  10.         super(context, attrs, defStyle);  
  11.         init(context);  
  12.     }  
  13.   
  14.     public CustomTextView(Context context, AttributeSet attrs) {  
  15.         super(context, attrs);  
  16.         init(context);  
  17.     }  
  18.   
  19.     private void init(Context context) {  
  20.                  setTextSize(context.getResources().getDimension(R.dimen.dimen_30sp));  
  21.         setOnClickListener(this);  
  22.         setOnFocusChangeListener(this);  
  23.     }  
  24.   
  25.   
  26.   
  27.     @Override  
  28.     public void onClick(View v) {  
  29.     }  
  30.   
  31.   
  32.     @Override  
  33.     public void onFocusChange(View v, boolean hasFocus) {  
  34.     }  
  35.   
  36.       
  37. }  

 

 

定义控件的时候,控件的文本大小定义成了30sp,为了适配考虑,30sp从dimens.xml文件里面获取。当时写这个控件时,屏幕分辨率为320x480,密度为160dpi,30sp=30dp=30px,后来需要适配480x640的分辨率,密度为240的屏幕,这时候30sp=30dp=45px。

 

但结果大大出乎我们意料,240dpi的屏幕,这个控件的字体不是45px,而是67.5px,显然不符合我们的要求。其中一个同事折腾了很久,向我请教,于是我怀疑setTextSize函数是不是做了什么手脚,于是查看源码,恍然大悟:

[java] view plain copy
  1. /** 
  2.  * Set the default text size to the given value, interpreted as "scaled 
  3.  * pixel" units.  This size is adjusted based on the current density and 
  4.  * user font size preference. 
  5.  * 
  6.  * @param size The scaled pixel size. 
  7.  * 
  8.  * @attr ref android.R.styleable#TextView_textSize 
  9.  */  
  10. @android.view.RemotableViewMethod  
  11. public void setTextSize(float size) {  
  12.     setTextSize(TypedValue.COMPLEX_UNIT_SP, size);  
  13. }  
  14.   
  15. /** 
  16.  * Set the default text size to a given unit and value.  See {@link 
  17.  * TypedValue} for the possible dimension units. 
  18.  * 
  19.  * @param unit The desired dimension unit. 
  20.  * @param size The desired size in the given units. 
  21.  * 
  22.  * @attr ref android.R.styleable#TextView_textSize 
  23.  */  
  24. public void setTextSize(int unit, float size) {  
  25.     Context c = getContext();  
  26.     Resources r;  
  27.   
  28.     if (c == null)  
  29.         r = Resources.getSystem();  
  30.     else  
  31.         r = c.getResources();  
  32.   
  33.     setRawTextSize(TypedValue.applyDimension(  
  34.         unit, size, r.getDisplayMetrics()));  
  35. }  

 

我们再看applyDimension函数:

[java] view plain copy
  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.     }  

原来setTextSize函数对应的单位本身就是sp。如果在240密度下,30sp=45px,setTextSize函数内部还需要乘以一个scaleDensity,那么setTextSize(30sp)实际设置的大小为30spx1sp=45x1.5=67.5px。

 

所以在做自定义控件的时候,设置控件文本大小的时候需要小心,否则搞了半天也找不到问题的症结所在。

 

 所以最好的做法是采用setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources().getDimension(R.dimen.dimen_30sp));


你可能感兴趣的:(getResources().getDimension(R.dimen.xsmall_text_size) 与 setTextSize(16)区别)