使用系统控件时,如layout_height/width参数这种,都是有两种值的
一种是枚举型wrap_content和match_parent/fill_parent,另一种则是具体的值200dp这样的
则自定义参数的申明则需要将两者结合起来
比如我们可以在自定义控件的宽高控制里加这么一个参数,equal_textsize,使用时保证drawable图片大小和文字一样
具体如下,在以前基础上添加enum子项,支持枚举值,value为了保证不和dimension冲突取负数~
自定义图片宽高属性中都可以添加一个enum
<attr name= "drawableWidth" format ="dimension">
<enum name ="equal_textsize" value="-2" />
</attr>
对应类代码如下
public class DrawableTextView extends TextView {
private static final int WRAP_DRAWABLE = -1;
private static final int EQUAL_TEXTSIZE = -2;
public DrawableTextView(Context context) {
this(context, null);
}
public DrawableTextView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public DrawableTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// 绑定attrs 属性
TypedArray ta = context.obtainStyledAttributes(attrs,
R.styleable. DrawableTextView);
// 获取自定义参数在使用时赋的具体值,由于值可能有两种不同的类型,所以自定义了一个方法
int widthPx = getIntOrDimen(ta,
R.styleable. DrawableTextView_drawableWidth, WRAP_DRAWABLE);
int heightPx = getIntOrDimen(ta,
R.styleable. DrawableTextView_drawableHeight, WRAP_DRAWABLE);
// 获取textview 的图片集合,上左下右方向共4个
Drawable[] drawables = getCompoundDrawables();
Drawable drawable = null;
for ( int i = 0; i < drawables. length; i++) {
if (drawables[i] != null) {
// 获取到某方向有图片的 drawable
drawable = drawables[i];
break;
}
}
// textsize用的是 sp作为size,而我们希望图片高度和文字部分一样,图片用的是 dp作为单位,
// 两者转为px的比例有时候是不同的(大部分情况下是一样的)
// 比如我用的平板, sp对应的scaledDensity为1.15, 而 dp对应的density为1.0,所以需要转换一下
Context c = getContext();
Resources r = c == null ? Resources. getSystem() : c.getResources();
DisplayMetrics metrics = r.getDisplayMetrics();
float scale = metrics. scaledDensity / metrics. density;
float tvSize = getTextSize();
// 如果是特殊枚举值EQUAL_TEXTSIZE,则计算 textsize对应的所需像素值
if (widthPx == EQUAL_TEXTSIZE) {
widthPx = ( int) (tvSize / scale + 0.5f);
}
// 如果是特殊枚举值EQUAL_TEXTSIZE,则计算 textsize对应的所需像素值
if (heightPx == EQUAL_TEXTSIZE) {
heightPx = ( int) (tvSize / scale + 0.5f);
}
// 根据获取到的宽高设置图片,达到对 drawable大小的控制
if (widthPx > 0 && heightPx > 0) {
drawable.setBounds(0, 0, widthPx, heightPx);
}
// 将改好的图片设置回去
setCompoundDrawables(drawables[0], drawables[1], drawables[2],
drawables[3]);
ta.recycle();
}
private int getIntOrDimen(TypedArray a, int index, int defValue) {
// 获取所需参数的类型值对象
TypedValue tv = a.peekValue(index);
int v = defValue;
if (tv != null) {
// 判断是否为dimension类型
boolean isDimen = tv. type == TypedValue.TYPE_DIMENSION;
// 如果是则获取dimension值,如果不是,则获取枚举项value对应的 int值
// 比如我们的例子里就是equal_textsize对应的整数-2
v = isDimen ? a.getDimensionPixelSize(index, defValue)
: a.getInt(index, defValue);
}
return v;
}
}
核心代码为getIntOrDimen,通过peekValue方法判断控件参数值类型,然后再利用对应方法获取到值,
统一转为int型返回,判断如果是特殊的-2则进行相关处理