相信很多同学在看完上一篇博客自定义控件6—自定义属性一 之后,一定有三个以为:
问题1 format =”reference|color”,比如自定义一个按钮,背景有可能是颜色也有可能是图片,该如何去获取该属性?
问题2 TypedValue是什么鬼东西?
问题3 getFraction(index, base, pbase, defValue);中的第2,3个参数是干什么的?
我的解决方法:
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);
}
}
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);
}
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