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