首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 移动开发 > 移动开发 >

由sp机构引发的惨案

2013-03-12 
由sp单位引发的惨案我的一个同事自定义了一个控件,控件代码如下: public class CustomTextView extends Te

由sp单位引发的惨案

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

 

public class CustomTextView extends TextView implements OnClickListener,OnFocusChangeListener {public CustomTextView(Context context) {super(context);init(context);}public CustomTextView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);init(context);}public CustomTextView(Context context, AttributeSet attrs) {super(context, attrs);init(context);}private void init(Context context) {                 setTextSize(context.getResources().getDimension(R.dimen.dimen_30sp));setOnClickListener(this);setOnFocusChangeListener(this);}@Overridepublic void onClick(View v) {}@Overridepublic void onFocusChange(View v, boolean hasFocus) {}    }

 

 

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

 

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

    /**     * Set the default text size to the given value, interpreted as "scaled     * pixel" units.  This size is adjusted based on the current density and     * user font size preference.     *     * @param size The scaled pixel size.     *     * @attr ref android.R.styleable#TextView_textSize     */    @android.view.RemotableViewMethod    public void setTextSize(float size) {        setTextSize(TypedValue.COMPLEX_UNIT_SP, size);    }    /**     * Set the default text size to a given unit and value.  See {@link     * TypedValue} for the possible dimension units.     *     * @param unit The desired dimension unit.     * @param size The desired size in the given units.     *     * @attr ref android.R.styleable#TextView_textSize     */    public void setTextSize(int unit, float size) {        Context c = getContext();        Resources r;        if (c == null)            r = Resources.getSystem();        else            r = c.getResources();        setRawTextSize(TypedValue.applyDimension(            unit, size, r.getDisplayMetrics()));    }

 

我们再看applyDimension函数:

public static float applyDimension(int unit, float value,                                       DisplayMetrics metrics)    {        switch (unit) {        case COMPLEX_UNIT_PX:            return value;        case COMPLEX_UNIT_DIP:            return value * metrics.density;        case COMPLEX_UNIT_SP:            return value * metrics.scaledDensity;        case COMPLEX_UNIT_PT:            return value * metrics.xdpi * (1.0f/72);        case COMPLEX_UNIT_IN:            return value * metrics.xdpi;        case COMPLEX_UNIT_MM:            return value * metrics.xdpi * (1.0f/25.4f);        }        return 0;    }

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

 

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

 

 


 

热点排行