自定义控件分为四个步骤
第一:自定义属性;
第二:获取自定义属性的值;
第三:重写onMeasure()方法;(视情况而定,本步骤不是必须的)
第四:重写onDraw()方法
自定义属性;
我们写一个MyTextView类,继承View,首先要重写构造方法;如下图
我们分析下父类的三种构造方法:
//使用java代码创建的时候调用
public MyTextView(Context context) {
super(context);
}
//AttributSet 是属性集合,因为xml文件会被反射成一个类,使用xml文件创建view的时候会调用该构造方法
public MyTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
//defStyle是default style的简写,当有指定样式的时候调用构造方法
public MyTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
我们分析了下三个构造方法的区别,但实际开发中我们总是希望能够调用参数较多的第三种构造方法,因为参数越多越能描述当前View的特性,以至于我们总是这么写;
public MyTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public MyTextView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyTextView(Context context) {
this(context, null);
}
然后我们可以在xml文件中为自定义的view添加相应的属性,但是我们发现我们现在能添加的属性大都是父类的属性,而我们自定义自己的view就是为了定义独特的属性,那我们该如何定义自己的属性呢?
第一步:我们在values文件夹下建立attrs文件
attrs文件如下
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- name 值一般和自定义的类名相同 ,也可以不一样 -->
<declare-styleable name="myTextView">
<!--
属性的类型
字符串:string
像素:dimension
颜色:color
引用:reference @
-->
<attr name="myText" format="string" />
<attr name="myTextSize" format="dimension" />
<attr name="myTextColor" format="color" />
</declare-styleable>
</resources>
第二步:在activity_xml中增加命名空间
这里介绍个小技巧;res后面跟的是当前应用的包名;可以在Mainfest中获取
xmlns:myandroid=”http://schemas.android.com/apk/res/com.example.zi_ding_yi_kong_jian”
第三步:获取控件的属性
<com.example.zi_ding_yi_kong_jian.myview.MyTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
myandroid:myText="张欣喜欢我"
myandroid:myTextColor="#13579a"
myandroid:myTextSize="10sp" />
然后可以在MytextView中获取所有的属性,这里介绍几种获取属性值的方法
方法一:
看下MyTextView代码:
package com.example.zi_ding_yi_kong_jian.myview;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
public class MyTextView extends View {
public MyTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
int count=attrs.getAttributeCount();
for(int i=0;i<count;i++){
String myName= attrs.getAttributeName(i);
String myValue= attrs.getAttributeValue(i);
Log.i("zhang_xin", myName+";"+myValue);
}
}
public MyTextView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyTextView(Context context) {
this(context, null);
}
}
这是打印输出结果:
与我们定义的属性一一对应;
但是这种方法有着一个明显的缺陷;那就是无法拿到引用的属性值;
如果我们的MyTextView的myText属性这么定义
myandroid:myText=”@string/myText”
我们看下打印的结果
为了解决这种情况我们只能用下面的方法了
看我们第二种方法的代码:
package com.example.zi_ding_yi_kong_jian.myview;
import com.example.zi_ding_yi_kong_jian.R;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;
public class MyTextView extends View {
public MyTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TypedArray ta = context.obtainStyledAttributes(attrs,
R.styleable.myTextView);
//数组中的第一个值
String myText = ta.getString(R.styleable.myTextView_myText);
// 指定颜色的默认值,如果没有定义该属性就返回默认值
int myTextColor = ta.getColor(R.styleable.myTextView_myTextColor,
Color.RED);
// sp的默认值可以使用下面的方法得到,如果是dp的默认值就是TypedValue.COMPLEX_UNIT_dip
int defaultValue = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_SP, 12, getResources()
.getDisplayMetrics());
int MyTestSize = (int) ta.getDimension(
R.styleable.myTextView_myTextSize, defaultValue);
Log.i("zhang_xin", "myText=" + myText + " myTextColor=" + myTextColor
+ " MyTestSize=" + MyTestSize);
ta.recycle();// 要回收 Be sure to call recycle() when done with them
}
public MyTextView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyTextView(Context context) {
this(context, null);
}
}
大家看这句代码
TypedArray ta =
context.obtainStyledAttributes(attrs, R.styleable.myTextView);
点击R.styleable.myTextView会发现R文件如下所示代码
public static final int[] myTextView = {
0x7f010000, 0x7f010001, 0x7f010002
};
数组的三个元素就是我们自定义的三个属性;
R.styleable.myTextView中的styleable是和declare-styleable标签相联系的;
我们看下打印输出结果,myandroid:myText=”@string/myText”也可以打印出内容,而不是引用的地址
好了,自定义view要分好几篇博客才可以讲完;本片博客讲的都是基础的;更深入的分析请看下面的博客