×

Android 自定义控件中单位转换

96
HelloVass
2015.11.30 11:58* 字数 216

在我们编写自定义控件的时候常常会需要进行单位转换,这个时候,这个再熟悉不过的工具类—— DisplayUtil 就会出现在我们的自定义控件中。

 private void init(Context context, AttributeSet attrs) {
    TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.DotViewLayout);
    // 默认 indicator 间距 10dp
    mIndicatorSpace = typedArray.getInt(R.styleable.DotViewLayout_indicator_space,
        DisplayUtil.dip2px(context, 10));

DisplayUtil 源码

public class DisplayUtil {

    public static int px2dip(Context context, float px) {
        float scale = context.getResources().getDisplayMetrics().density;
        return (int) (px / scale + 0.5f);
    }

    public static int dip2px(Context context, float dp) {
        float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dp * scale + 0.5f);
    }
}

但是,有时候又懒得 copy 这个工具类。后来发现,Android Framework 是提供了相应的工具类供我们使用的。

TypedValue 中的 applyDimension() 方法:

    /**
     * 
     * @param unit The unit to convert from.
     * @param value The value to apply the unit to.
     * @param metrics Current display metrics to use in the conversion -- 
     *                supplies display density and scaling information.
     */
    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;
    }

该方法将传入的 value 值转变为标准尺寸,那么我们的自定义控件就可以不用依赖 DisplayUtil

之前的栗子就可以这么写:

mIndicatorSpace = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10,getResources().getDisplayMetrics());

TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.DotViewLayout);
// 默认 indicator 间距 10dp
mIndicatorSpace = typedArray.getInt(R.styleable.DotViewLayout_indicator_space,mIndicatorSpace);

笔者认为:虽然自定义控件了多了好多代码,但是,减少了对 DisplayUtil 的依赖(哈哈,不用粘贴 DisplayUtil 了),我们的自定义控件发布时也变得 clean 多了!

Android
Web note ad 1