创建一个View类
一个设计良好的自定义视图,如同其他精心设计的类。它封装了一组简单易用特定的功能接口,
有效的利用CPU和内存等。除了是一个精心设计的类,一个自定义的视图应该具有以下特性:
1.符合Android的标准
2.提供一个自定义的样式与xml布局文件
3.发送可访问事件
4.与多个Android平台兼容
子类视图
所有Android framework中的视图类都继承于View。你自定义的view也能直接继承于View,如果
要节省时间,你也可以继承于View的子类视图,列如Button。
为了允许Android Developer Tools与你的程序交互,你需要至少提供一个构造函数,以Context
和AttributeSet对象为参数。这个构造函数允许layout edit来创建和编辑你的view的实例。
自定义属性
要给你的用户界面添加一个嵌入的view,你需要在XML中定义它,并且通过xml属性来控制它
的显示和行为。一个良好的自定义视图也能够在XML中添加和定义样式。为了达到这个目的,
你需要做:
1.为你的view的属性定义一个<declare-styleable>资源元素
2.在XML布局文件中定义属性的值
3.在运行的时候检索属性值
4.为你的视图应用属性值
<declare-styleable>元素被定义在res/value/attrs.xml文件中:
上面的代码声明了两个自定义属性,showText和labelPosition,它们属于一个叫PieChart的属
性元素。为了方便起见,这个元素的名字与类的命名相同。
一旦你定义了自定义属性,你可以在xml布局文件中使用它,就像内嵌的其他属性。这两者的
不同之处就是你自定义的属性属于不同的命名空间。它不是属于http://schemas.android.com/apk/res/android,
而是属于http://schemas.android.com/apk/res/[your package name]:
为了避免重复长的命名空间,这个例子使用了一个xmlns指令。该指令将custom指定为命名空
间http://schemas.android.com/apk/res/com.example.customviews的别名。你可以选择任何你
想选的空间别名。
注意为自定义的view添加到xml布局文件中的名称。这是自定义视图的完全限定名称。如果你
的视图是一个内部类,你还要限定外部类的名称。例如,在PieChart类的一个内部类PieView,
要使用这个自定义类,可使用标签:com.example.customviews.charting.PieChart PieView。
应用自定义属性
当从一个xml布局文件中创建一个view时,所有该view的属性都从xml布局文件中获取,并将
值以参数AttributeSet传递到该view的构造函数中。尽管可以从AttributeSet中直接读取值,但
这样做有下面一些不好处:
1.没有解决在attribute中资源引用
2.样式不适用
相反,将AttributeSet传递给obtainStyledAttributes()。这个方法返回一个TypedArray数组,
包含了所有的样式属性值。
Android资源编译器为了使obtainStyledAttribute()方法更容易,为此做了很多工作。对于每
一个在res目录下的<declare-styleable>资源,生成的R.JAVA文件定义了一个属性id的数组和
一个常量集合,定义了在数组中的每一个属性的索引。你使用预定义的常量从TypedArray中
读取属性。
请注意TypeArray对象是一个共享的资源,在使用完后必须回收。
添加属性和事件
属性集合是一个很有力的方式来控制view的行为和显示,但他们只有在view被初始化后才能被
读取。为了提供动态的行为操作,为每一个自定义的属性实现getter和setter。
注意,setShowText方法调用了invalidate()和requestLayout()。这些调用对于确保行为
确实被使用是非常重要的。在每次对view的显示属性做出改变时,必须要调用invalidate,这
告诉系统,系统需要重新绘制界面。同样的,当改变view的属性会影响view的大小或形状时,
你需要请求重新布局。
自定义的view也应该支持事件监听,来与重要的事件进行通信。例如,PieChart暴露了一个
自定义的事件叫OnCurrentItemChanged,当用户选择一个新的pie slice时来触发相关的监听
器。
一个设计良好的自定义视图,如同其他精心设计的类。它封装了一组简单易用特定的功能接口,
有效的利用CPU和内存等。除了是一个精心设计的类,一个自定义的视图应该具有以下特性:
1.符合Android的标准
2.提供一个自定义的样式与xml布局文件
3.发送可访问事件
4.与多个Android平台兼容
子类视图
所有Android framework中的视图类都继承于View。你自定义的view也能直接继承于View,如果
要节省时间,你也可以继承于View的子类视图,列如Button。
为了允许Android Developer Tools与你的程序交互,你需要至少提供一个构造函数,以Context
和AttributeSet对象为参数。这个构造函数允许layout edit来创建和编辑你的view的实例。
class PieChart extends View {
public PieChart(Context context, AttributeSet attrs) {
super(context, attrs);
}
}
public PieChart(Context context, AttributeSet attrs) {
super(context, attrs);
}
}
自定义属性
要给你的用户界面添加一个嵌入的view,你需要在XML中定义它,并且通过xml属性来控制它
的显示和行为。一个良好的自定义视图也能够在XML中添加和定义样式。为了达到这个目的,
你需要做:
1.为你的view的属性定义一个<declare-styleable>资源元素
2.在XML布局文件中定义属性的值
3.在运行的时候检索属性值
4.为你的视图应用属性值
<declare-styleable>元素被定义在res/value/attrs.xml文件中:
<resources>
<declare-styleable name="PieChart">
<attr name="showText" format="boolean" />
<attr name="labelPosition" format="enum">
<enum name="left" value="0"/>
<enum name="right" value="1"/>
</attr>
</declare-styleable>
</resources>
<declare-styleable name="PieChart">
<attr name="showText" format="boolean" />
<attr name="labelPosition" format="enum">
<enum name="left" value="0"/>
<enum name="right" value="1"/>
</attr>
</declare-styleable>
</resources>
上面的代码声明了两个自定义属性,showText和labelPosition,它们属于一个叫PieChart的属
性元素。为了方便起见,这个元素的名字与类的命名相同。
一旦你定义了自定义属性,你可以在xml布局文件中使用它,就像内嵌的其他属性。这两者的
不同之处就是你自定义的属性属于不同的命名空间。它不是属于http://schemas.android.com/apk/res/android,
而是属于http://schemas.android.com/apk/res/[your package name]:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android=" http://schemas.android.com/apk/res/android"
xmlns:custom=" http://schemas.android.com/apk/res/com.example.customviews">
<com.example.customviews.charting.PieChart
custom:showText="true"
custom:labelPosition="left" />
</LinearLayout>
<LinearLayout xmlns:android=" http://schemas.android.com/apk/res/android"
xmlns:custom=" http://schemas.android.com/apk/res/com.example.customviews">
<com.example.customviews.charting.PieChart
custom:showText="true"
custom:labelPosition="left" />
</LinearLayout>
为了避免重复长的命名空间,这个例子使用了一个xmlns指令。该指令将custom指定为命名空
间http://schemas.android.com/apk/res/com.example.customviews的别名。你可以选择任何你
想选的空间别名。
注意为自定义的view添加到xml布局文件中的名称。这是自定义视图的完全限定名称。如果你
的视图是一个内部类,你还要限定外部类的名称。例如,在PieChart类的一个内部类PieView,
要使用这个自定义类,可使用标签:com.example.customviews.charting.PieChart PieView。
应用自定义属性
当从一个xml布局文件中创建一个view时,所有该view的属性都从xml布局文件中获取,并将
值以参数AttributeSet传递到该view的构造函数中。尽管可以从AttributeSet中直接读取值,但
这样做有下面一些不好处:
1.没有解决在attribute中资源引用
2.样式不适用
相反,将AttributeSet传递给obtainStyledAttributes()。这个方法返回一个TypedArray数组,
包含了所有的样式属性值。
Android资源编译器为了使obtainStyledAttribute()方法更容易,为此做了很多工作。对于每
一个在res目录下的<declare-styleable>资源,生成的R.JAVA文件定义了一个属性id的数组和
一个常量集合,定义了在数组中的每一个属性的索引。你使用预定义的常量从TypedArray中
读取属性。
public PieChart(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.getTheme().obtainStyledAttributes(
attrs,
R.styleable.PieChart,
0, 0);
try {
mShowText = a.getBoolean(R.styleable.PieChart_showText, false);
mTextPos = a.getInteger(R.styleable.PieChart_labelPosition, 0);
} finally {
a.recycle();
}
}
super(context, attrs);
TypedArray a = context.getTheme().obtainStyledAttributes(
attrs,
R.styleable.PieChart,
0, 0);
try {
mShowText = a.getBoolean(R.styleable.PieChart_showText, false);
mTextPos = a.getInteger(R.styleable.PieChart_labelPosition, 0);
} finally {
a.recycle();
}
}
请注意TypeArray对象是一个共享的资源,在使用完后必须回收。
添加属性和事件
属性集合是一个很有力的方式来控制view的行为和显示,但他们只有在view被初始化后才能被
读取。为了提供动态的行为操作,为每一个自定义的属性实现getter和setter。
public boolean isShowText() {
return mShowText;
}
public void setShowText(boolean showText) {
mShowText = showText;
invalidate();
requestLayout();
}
return mShowText;
}
public void setShowText(boolean showText) {
mShowText = showText;
invalidate();
requestLayout();
}
注意,setShowText方法调用了invalidate()和requestLayout()。这些调用对于确保行为
确实被使用是非常重要的。在每次对view的显示属性做出改变时,必须要调用invalidate,这
告诉系统,系统需要重新绘制界面。同样的,当改变view的属性会影响view的大小或形状时,
你需要请求重新布局。
自定义的view也应该支持事件监听,来与重要的事件进行通信。例如,PieChart暴露了一个
自定义的事件叫OnCurrentItemChanged,当用户选择一个新的pie slice时来触发相关的监听
器。