自定义控件-3.加强用法,多重参数类型

来源:互联网 发布:macbook平面设计软件 编辑:程序博客网 时间:2024/06/08 01:17
 使用系统控件时,如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则进行相关处理


0 0
原创粉丝点击