在某些情况下,你可能有更简单的方法去创建你的组件。如果你应经有了一个非 常类似的组件,你所要做的只是简单的从这个组件派生出你的组件,重在其中一 些有必要修改的方法。通过完全自定义组件的方法你也可以同样的实现,但通过 冲View派生产生新的组件,你可以简单获取一些已经存在的处理机制,这些很
例如,在SDK中有一个NotePad的例子(NotePad application )。该例子演
示了很多Android平台实用的细节,例如你会学到从EditView派生出能够自动
换行的记事本。这还不是一个完美的例子,因为相比早期的版本来说,这些API 已经感变了很多,但它确实说明了一些问题。
如果你还未查看该程序,现在你就可以在Eclipse中导入记事本例程(或仅通过 提供的链接查看相应的源代码)。特别是查看NoteEditor.java 中的MyEditText 的定义。
下面有几点要注意的地方:
1. 声明(The Definition)
这个类是通过下面一行代码来定义的:
public static class MyEditText extends EditText
o 它是定义在NoteEditor activity类里面的,但是它是共有的
(public),因此如果有必要,它可以通过
NoteEditor.MyEditText 从NoteEditor 外面来调用。
o 它是static类(静态类),意味着不会出现所谓的通过父类访问 数据的“虚态方法”, 这样就使该类成为一个可以不严重依赖
NoteEditor的单独类。对于不需要从外部类访问的内联类的创建,
这是一个很清晰地思路,保证所产生的类很小,并且允许它可以被其 他的类方便的调用。
o 它是EditText类的扩展,它是我们选择的用来自定义的父类。
当我们完成以后,新的类就可以作为一个普通的EditText来使用。
2. 类的初始化
一般来说,父类是首先调用的。进一步来说,这不是一个默认的构造函数,
而是一个带参数的构造函数。因为EditText是使用从XML布局文件提 取出来的参数进行创建,因此我们的构造函数也要取出参数并且将这些参 数传递给父类。
3. 方法重载
在本例中,仅对onDraw()一个方法进行重载。但你可以很容易地为你的 定制组件重载其他需要的方法。
对于记事本例子来说,通过重载onDraw()方法我们可以在EidtView 的画布(canvas)上绘制蓝色的线条(canvas类是通过重写的onDraw() 方法传递)。该函数快要结束时要调用super.onDraw()函数。父类的 方法是应该调用,但是在这个例子里面,我们是在我们划好了蓝线之后调 用的。
4. 使用定制组件
现在,我们已经有自己定制的组件了,但是应该怎样使用它呢?在记事本 例子中,定制的组件直接在预定义的布局文件中使用,让我们看一看 res/layout目录中的note_editor.xml 文件。
<view
xmlns:android="http://schemas.android.com/apk/res/an droid"
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" />
o 该自定义组件在XML中是作为一个一般的View类来创建的,并 且是通过全路径包来描述的。注意这里内联类是通过
NoteEditor$MyEditText 来表示的,这是Java编程中引用内联 类的标准方法。
o 在定义中的其他属性和参数将传递给定制组件的构造函数,然后才
传到EditText构造函数中,因此这些参数也是你使用EditText组件
的参数。注意,这里你也可以增加你自己的参数,我们将在下面讨论
这就是你全部需要做的,诚然这是一个简单的例子。但问题的关键是:你的需求 有多复杂,那么你的自定义组件就有多么复杂。
一个更为复杂的组件可能需要重载更多的on系列函数,并且还要很多特有的函 数来充分实现自定义组件的功能。唯一的限制就是你的想象力和你需要组件去执 行什么工作。