Android基于View和ViewGroup基础类提供了复杂和强大的组件模型来创建UI。比如一些小部件和布局。
小部件包括Button,TextView,EditText等,布局包括LinearLayout,FrameLayout等。
如果没有需要的部件和布局,你可以创建自己的View子类,如果想对部件和布局做一些调整的话,你自需要继承这些类,覆盖一些方法。
创建自己的View子类可以让你精确的控制界面外观和和屏幕元素的功能。下面是一些你可以实现的例子:
- 完全自定义的View,比如,使用2D图形做一个音量控制。
- 组合一些View组件,比如,一个组合框(包含列表和文本),一个多面板选择器(分为左右两个列表,可以同时选择)。
- 扩展EditText等组件。
- 你应该捕获触屏等事件,然后用自己的方法处理他们。
自定义组件的基本方法
- 扩展一个已经存在的View类或者子类。
- 重写那些以“on”开头的方法,比如,onDraw(),onMeasure(),onKeyDown()。
- 使用新的扩展类。
完全自定义组件
- 继承View。
- 创建构造函数,从XML中取得属性,当然你可以创建自己的属性。
- 创建自己的事件监听,属性访问和修改函数。
- 重写onMeasure()和onDraw()方法。
- 重写你需要的on...方法。
扩展onDraw()和onMeasure()
onDraw()方法传递Canvas来绘制你需要的2D图形。
onMessure()是组件和容器之间渲染时要调用的方法。它的主要工作包括:
- 重写onMeasure,传递进来宽高两个参数。
- 计算你的组件需要的宽高,最好不要大于传递进来的宽高。
- 调用setMeasureDimension(int width, int height)。
下面是另外一些可扩展的标准方法:
Category | Methods | Description |
---|---|---|
Creation | Constructors | 构造函数 |
|
view在XML中被使用后调用 | |
Layout |
|
指定尺寸需求时调用 |
|
分配尺寸和位置时调用 | |
|
view的大小发生改变时调用 | |
Drawing |
|
渲染内容时调用 |
Event processing |
|
按键按下时调用 |
|
按键抬起时调用 | |
|
轨迹球移动时调用 | |
|
触摸屏幕时调用 | |
Focus |
|
view获得或者失去焦点时调用 |
|
包含view的窗口获得或者失去焦点时调用 | |
Attaching |
|
view附加到窗口时调用 |
|
从窗口分离时调用 | |
|
包含view的窗口可见度发生变化时调用 |
组合现有组件
在Android中就有两个组合的例子:Spinner和AutoCompleteTextView。
创建一个简单的Combo box组合组件需要做的是:
- 继承Layout类,可以是一LinearLayout。而且其他layout可以会被插入进来,所以组合组件可以是任意复杂和结构化的。比如在Activity中既可以在XML声明然后调用,可可以直接用代码实例化。
- 在构造函数中调用父类构造函数,传递必要的参数。
- 创建事件监听。
- 创建自己的属性访问和修改器。
- 扩展Layout类时,你不需要重写onDraw()和onMeasure()方法。
- 重写你需要的on...方法。
使用组合组件的优势是:
- 你可以在XML中直接声明组件,或者在程序中嵌入。
- 不需要重写onDraw和onMeasure方法。
- 快速复用单一组件构造复杂的组件。
修改已经存在的View
在SDK中的NotePad实例里面就扩展了EditText来实现一个多行的记事本,具体实现如下:
- 定义
类的定义:
public static class MyEditText extends EditText
a. 被定义为NoteEditor的内部类,不过它的public的,所以可以在外部使用NoteEditor.MyEditText访问。
b. 它是static的,可以通过父类直接调用访问。
c. 扩展自EditText。 - 类的初始化
构造函数中,要先调用父类。 - 重写函数
重写onDraw方法,在EditText下面绘制蓝色的线。 - 使用自定义组件
在布局文件中:<view class="com.android.notepad.NoteEditor$MyEditText" id="@+id/note" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@android:drawable/empty" android:padding="10dip" android:scrollbars="vertical" android:fadingEdge="vertical" />
如果不是内部类的实现,可以使用下面的方法:
<com.android.notepad.MyEditText id="@+id/note" ... />