Android 中使用自定义属性的一般步骤:

  1. 定义declare-styleable,添加attr
  2. 使用TypedArray获取自定义属性
  3. 设置到View上

Sample

注意:

  • attr可以单独定义,不放在styleable中
  • 可以使用android内置attr,而不用声明format
  • 可以不用TypedArray来获取

attrs.xml

<?xml version="1.0" encoding="utf-8"?><resources>    <declare-styleable name="test">        <attr name="size" format="dimension" />        <attr name="android:textColor" />    declare-styleable>resources>

MyView:

/** * Created by bobomee on 16/1/25. */public class MyView extends View {    String T = this.getClass().getSimpleName();    private float mSize;    private int mBackGround;    private Paint mPaint;    public MyView(Context context) {        this(context, null);    }    public MyView(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public MyView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        handleAttrs(context, attrs, defStyleAttr);    }    @TargetApi(Build.VERSION_CODES.LOLLIPOP)    public MyView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {        super(context, attrs, defStyleAttr, defStyleRes);        handleAttrs(context, attrs, defStyleAttr);    }    private void handleAttrs(Context context, AttributeSet attrs, int defStyleAttr) {        //Retrieve styles attributes        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.test, defStyleAttr, 0);        int defaultSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 20, context.getResources().getDisplayMetrics());        mSize = ta.getDimension(R.styleable.test_size, defaultSize);        mBackGround = ta.getColor(R.styleable.test_android_textColor, Color.WHITE);        mPaint = new Paint();        mPaint.setAntiAlias(true);        mPaint.setColor(mBackGround);        Log.d(T, "mSize = " + mSize + " , mBackGround = " + mBackGround);        ta.recycle();    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        canvas.drawCircle(0,0,mSize,mPaint);    }}

activity.xml

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:gravity="center"    android:background="@color/colorAccent">    <com.bobomee.android.attrstest.MyView        android:layout_width="200dp"        android:layout_height="200dp"        android:background="@color/colorPrimary"        android:textColor ="#00ffab"        app:size="50dp" />RelativeLayout>

其中declare-styleable不是自定义View
android:textColor是内置属性,没有指定format

运行效果如下:

AttributeSet&&TypedArray

在自定义View中,除了第一个构造函数,都包含一个参数AttributeSet(View属性),可以通过它来获取属性,而不用TypedArray

  private void handleAttrs(Context context, AttributeSet attrs, int defStyleAttr) {        //Retrieve styles attributes//        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.test, defStyleAttr, 0);////        int defaultSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 20, context.getResources().getDisplayMetrics());//        mSize = a.getDimension(R.styleable.test_size, defaultSize);////        mBackGround = a.getColor(R.styleable.test_android_textColor, Color.WHITE);////        mPaint = new Paint();//        mPaint.setAntiAlias(true);//        mPaint.setColor(mBackGround);//        Log.d(T, "mSize = " + mSize + " , mBackGround = " + mBackGround);        int count = attrs.getAttributeCount();        for (int i = 0; i < count; i++) {            String attrName = attrs.getAttributeName(i);            String attrVal = attrs.getAttributeValue(i);            Log.e(T, "attrName = " + attrName + " , attrVal = " + attrVal);        }    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);//        canvas.drawCircle(0,0,mSize,mPaint);    }

logcat信息:

01-25 23:45:04.989 16613-16613/com.bobomee.android.attrstest E/MyView: attrName = textColor , attrVal = #ff00ffab01-25 23:45:04.989 16613-16613/com.bobomee.android.attrstest E/MyView: attrName = background , attrVal = @213142734701-25 23:45:04.989 16613-16613/com.bobomee.android.attrstest E/MyView: attrName = layout_width , attrVal = 200.0dip01-25 23:45:04.989 16613-16613/com.bobomee.android.attrstest E/MyView: attrName = layout_height , attrVal = 200.0dip01-25 23:45:04.989 16613-16613/com.bobomee.android.attrstest E/MyView: attrName = size , attrVal = 50.0dip

layout.xml

  <com.bobomee.android.attrstest.MyView        android:layout_width="200dp"        android:layout_height="200dp"        android:background="@color/colorPrimary"        android:textColor ="#00ffab"        app:size="50dp" />

可见,background是一个ID:@2131427347,其他的都是实际值。

有了id,就可以通过id来得到具体值了。

修改代码如下:

dimens.xml

 <dimen name="width">200dpdimen>    <dimen name="height">200dpdimen>    <dimen name="size">50dpdimen>

activity_main.xml

<com.bobomee.android.attrstest.MyView        android:layout_width="@dimen/width"        android:layout_height="@dimen/height"        app:size="@dimen/size" />

MyView

int count = attrs.getAttributeCount();        for (int i = 0; i < count; i++) {            String attrName = attrs.getAttributeName(i);            int resId = attrs.getAttributeResourceValue(i, 0);            float attrVal = getResources().getDimension(resId);            Log.e(T, "attrName = " + attrName + " , attrVal = " + attrVal);        }

logcat信息:

01-26 00:21:14.189 28485-28485/com.bobomee.android.attrstest E/MyView: attrName = layout_width , attrVal = 400.001-26 00:21:14.189 28485-28485/com.bobomee.android.attrstest E/MyView: attrName = layout_height , attrVal = 400.001-26 00:21:14.189 28485-28485/com.bobomee.android.attrstest E/MyView: attrName = size , attrVal = 100.0

可以看到自定义属性值获取到了,可见TypedArray可以直接获取到引用类型的值,而不是id

declare-styleable

既然说attr不一定要定义在styleable中,那我么来尝试一下。
attr.xml

<?xml version="1.0" encoding="utf-8"?><resources>            <attr name="size" format="dimension" />            resources>

android:textColor如果不注釋掉,會報如下錯誤,也就是定义好的属性就可以直接使用了

Error:(3) Attribute "android:textColor" has already been defined

layout

 <com.bobomee.android.attrstest.MyView        android:layout_width="@dimen/width"        android:layout_height="@dimen/height"        android:background="@color/colorPrimary"        app:size="@dimen/size"        android:textColor ="@color/textColor"        android:textSize = "30sp"        />

MyView

/** * Created by bobomee on 16/1/25. */public class MyView extends View {    String T = this.getClass().getSimpleName();    private float mSize;    private int mBackGround;    private Paint mPaint;    private float mTextSize;    final int[] custom_attrs = {android.R.attr.textSize,android.R.attr.textColor,R.attr.size};    final int TSIZE = 0;    final int BACKGROUNG = 1;    final int SIZE = 2;    public MyView(Context context) {        this(context, null);    }    public MyView(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public MyView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        handleAttrs(context, attrs, defStyleAttr);    }    @TargetApi(Build.VERSION_CODES.LOLLIPOP)    public MyView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {        super(context, attrs, defStyleAttr, defStyleRes);        handleAttrs(context, attrs, defStyleAttr);    }    private void handleAttrs(Context context, AttributeSet attrs, int defStyleAttr) {        //Retrieve styles attributes//        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.test, defStyleAttr, 0);//          int defaultSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 20, context.getResources().getDisplayMetrics());//        mSize = ta.getDimension(R.styleable.test_size, defaultSize);////        mBackGround = ta.getColor(R.styleable.test_android_textColor, Color.WHITE);        TypedArray ta = context.obtainStyledAttributes(attrs,custom_attrs);        mSize = ta.getDimension(SIZE, defaultSize);        mBackGround = ta.getColor(BACKGROUNG, Color.WHITE);        mTextSize = ta.getDimension(TSIZE,defaultSize);        mPaint = new Paint();        mPaint.setAntiAlias(true);        mPaint.setColor(mBackGround);        Log.d(T, "mSize = " + mSize + " , mBackGround = " + mBackGround+ " , mTextSize = " + mTextSize);//        int count = attrs.getAttributeCount();//        for (int i = 0; i < count; i++) {//            String attrName = attrs.getAttributeName(i);//            int resId = attrs.getAttributeResourceValue(i, 0);//            float attrVal = getResources().getDimension(resId);//            Log.e(T, "attrName = " + attrName + " , attrVal = " + attrVal);//        }        ta.recycle();    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        canvas.drawCircle(0, 0, mSize, mPaint);    }}

logcat

13541-13541/com.bobomee.android.attrstest D/MyView: mSize = 100.0 , mBackGround = -16711765 , mTextSize = 60.0

運行效果同上圖

在这里我们定义了一个attr数组,这里需要注意的是android本身定义的attr,需要放在数组的前面,如果有多个android属性,角标和数组定义需要对应即可,不用管layout中定义的顺序。
如果按照传统的方式,我们到android自动生成的R文件下看一下,会发现

  public final class R {        public static final class attr {            public static final int size=0x7f010110;        }        public static final class styleable {            public static final int[] test = {                    0x01010095, 0x01010098, 0x7f010110            };            public static final int test_android_textColor = 1;            public static final int test_android_textSize = 0;            public static final int test_size = 2;        }    }

通过declare-styleable可以在R文件下自动生成一个attr id 的数组 和下标,此外declare-styleable可以将相关属性分组,方便管理,同时以自定义View的名称命名,可以方便找到。

总结

  • 在android我们在attr下面申明属性,即可在R文件中生成相应的id,我们同时可以引用android定义好的attr属性。
  • 通过declare-styleable,可以在R文件中生成一个相应的attr集合的数组和角标,方便获取和分组管理,可以不用声明
  • TypedArray可以通过AttributeSet获取styleable数组中的自定义属性集合,从而获取属性值

参考:
Android 深入理解Android中的自定义属性

更多相关文章

  1. Android之创建自定义属性
  2. 下拉刷新、上拉加载实战:带你理解自定义View整个过程
  3. Gradle for Android(安卓)第七篇( Groovy入门 )
  4. android 工具 HierarchyViewer activity树结构查看
  5. Android(安卓)性能最佳实践 1
  6. Android(安卓)L下载
  7. Android实现发送短信验证码倒计时功能示例
  8. android GSM+CDMA基站定位
  9. 在Ubuntu中获取Android源文件(相关整理&摘抄)

随机推荐

  1. Android关于ListView显示SD卡上的Bitmap
  2. android 使用InputFilter 对金额和长度进
  3. Android 数据查询query函数参数解析
  4. 需要完善的笔记
  5. 可动态布局的Android抽屉之完整篇
  6. android 闪屏还是会出现黑屏问题
  7. android的webview调用javascript函数并得
  8. cyanogenmod 内核编译简记
  9. Android中设置EditText获得焦点时不弹出
  10. 百度地图移动版API 1.2.2版本(Android)地图