自定义控件7---自定义属性二

相信很多同学在看完上一篇博客自定义控件6—自定义属性一 之后,一定有三个以为:

问题1 format =”reference|color”,比如自定义一个按钮,背景有可能是颜色也有可能是图片,该如何去获取该属性?
问题2 TypedValue是什么鬼东西?
问题3 getFraction(index, base, pbase, defValue);中的第2,3个参数是干什么的?

问题1

我的解决方法:

    if (a.hasValue(R.styleable.CustomVolumControlBar_bg)) {
            mImage=null;
            //如果有图片则获取bitmap
            mImage = BitmapFactory.decodeResource(getResources(), a.getResourceId(attr, 0));
            //如果无图片则获取color
            if(mImage==null){
                mColor=a.getColor(attr, Color.RED);
            }
    }

问题2

API—TypedValue | Android 开发者

引用:
TypedValue.applyDimension 中dp和sp之间转化的真相 - 那些人追过的年 - 博客园

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)中的代码我们来看下

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;
    }

其中单位为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

将代码运行实际结果与判断结果一致。

转化dp-px,px-dp,sp-px,px-sp

  //转换dip为px 
  public static int convertDipOrPx(Context context, int dip) { 
      float scale = context.getResources().getDisplayMetrics().density; 
      return (int)(dip*scale + 0.5f*(dip>=0?1:-1)); 
  } 

  //转换px为dip 
  public static int convertPxOrDip(Context context, int px) { 
      float scale = context.getResources().getDisplayMetrics().density; 
     return (int)(px/scale + 0.5f*(px>=0?1:-1)); 
 } 

  //转换sp为px 
  public static int sp2px(Context context, float spValue) {
        float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
        return (int) (spValue * fontScale + 0.5f);
 }

  //转换px为sp
  public static int px2sp(Context context, float pxValue) {
        float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
        return (int) (pxValue / fontScale + 0.5f);
 }

问题3

getFraction(index, base, pbase, defValue);
attrs.xml:
  <item name="fraction" type="fraction">5%</item>
  <item name="parent_fraction" type="fraction">2%p</item>

打印结果:
// 0.05f
getResources().getFraction(R.fraction.fraction, 1, 1);
// 0.02f
getResources().getFraction(R.fraction.parent_fraction, 1, 1);
// 0.10f
getResources().getFraction(R.fraction.fraction, 2, 1);
// 0.10f
getResources().getFraction(R.fraction.fraction, 2, 2);
// 0.04f
getResources().getFraction(R.fraction.parent_fraction, 1, 2);
// 0.04f
getResources().getFraction(R.fraction.parent_fraction, 2, 2);

具体的文档我就不翻译了,简单来说就是:
1 自定义百分数有两种格式,5%和5%p
2 两者的区别在于,如果5%,那么在调用getFraction()时,会*base
如果是5%p,那么会*pbase

引用:
Android res.getFraction() - 学习记录 - 博客频道 - CSDN.NET
android - How does one use Resources.getFraction()? - Stack Overflow

你可能感兴趣的:(自定义控件)