`

【翻译】(23)自定义组件

 
阅读更多

 

【翻译】(23)自定义组件

 

see

http://developer.android.com/guide/topics/ui/custom-components.html

 

原文见

http://developer.android.com/guide/topics/ui/custom-components.html

 

-------------------------------

 

Custom Components

 

自定义组件

 

-------------------------------

 

In this document

 

本文目录

 

* The Basic Approach 基本方法

* Fully Customized Components 完全自定义组件

* Compound Controls 复合控件

* Modifying an Existing View Type 修改一个现存视图类型

 

-------------------------------

 

Android offers a sophisticated and powerful componentized model for building your UI, based on the fundamental layout classes: View and ViewGroup. To start with, the platform includes a variety of prebuilt View and ViewGroup subclasses — called widgets and layouts, respectively — that you can use to construct your UI.

 

Android提供一个复杂和强大的组件化模型用于构建你的用户界面,基于基础布局类:View和ViewGroup。为了开始,平台包含不同的预构建View和ViewGroup子类——对应地称为部件和布局——你可以用它们构造你的用户界面。

 

A partial list of available widgets includes Button, TextView, EditText, ListView, CheckBox, RadioButton, Gallery, Spinner, and the more special-purpose AutoCompleteTextView, ImageSwitcher, and TextSwitcher.

 

一个可用部件的部分列表包括Button,TextView,EditText,ListView,CheckBox,RadioButton,Gallery,Spinner,以及更特定目的的AutoCompleteTextView,ImageSwitcher以及TextSwitcher。

 

Among the layouts available are LinearLayout, FrameLayout, RelativeLayout, and others. For more examples, see Common Layout Objects.

 

在可用的布局中有LinearLayout,FrameLayout,RelativeLayout,以及其它。想获取更多示例,请参见一般布局对象。

 

If none of the prebuilt widgets or layouts meets your needs, you can create your own View subclass. If you only need to make small adjustments to an existing widget or layout, you can simply subclass the widget or layout and override its methods.

 

如果没有预构建部件或布局满足你的需要,你可以创建你自己的View子类。如果你只需要对现存部件或布局做小的调整,你可以简单地子类化部件或布局并覆盖它的方法。

 

Creating your own View subclasses gives you precise control over the appearance and function of a screen element. To give an idea of the control you get with custom views, here are some examples of what you could do with them:

 

创建你自己的View子类让你能精确控制一个屏幕元素的外观和功能。为了给你一个你能控制自定义视图的主意,这里有一些你可以用来处理它们的示例。

 

* You could create a completely custom-rendered View type, for example a "volume control" knob rendered using 2D graphics, and which resembles an analog electronic control.

 

* 你可以创建一个完全定制渲染的View类型,例如一个用二维图形渲染的“音量控制”旋钮,它好像一个模拟电子控件。

 

* You could combine a group of View components into a new single component, perhaps to make something like a ComboBox (a combination of popup list and free entry text field), a dual-pane selector control (a left and right pane with a list in each where you can re-assign which item is in which list), and so on.

 

* 你可以组合一组View组件进一个新的单一组件,可能做出一些东西像ComboBox(一个弹出列表和自由进入的文本域的组合),一个双窗格选择器控件(组右窗格带有一个列表,其中你可以重新赋予哪个条目在哪个列表),等等。

 

* You could override the way that an EditText component is rendered on the screen (the Notepad Tutorial uses this to good effect, to create a lined-notepad page).

 

* 你可以覆盖EditText组件在屏幕上的渲染方式(记事本教程使用它达到良好效果,以创建单行簿式的页面)。

 

* You could capture other events like key presses and handle them in some custom way (such as for a game).

 

* 你可以捕获其它事件像键盘按下和用一些自定义方式处理它们(诸如对于一个游戏)。

 

The sections below explain how to create custom Views and use them in your application. For detailed reference information, see the View class.

 

下面几个章节解析如何创建自定义View并且在应用程序中使用它们。想获取详细参考信息,请参见View类。

 

-------------------------------

 

The Basic Approach

 

基本方法

 

Here is a high level overview of what you need to know to get started in creating your own View components:

 

这里是一个你需要知道的高层次概览以开始创建你自己的View组件:

 

1. Extend an existing View class or subclass with your own class.

 

1. 用你自己的类扩展一个现存View类或子类。

 

2, Override some of the methods from the superclass. The superclass methods to override start with 'on', for example, onDraw(), onMeasure(), and onKeyDown(). This is similar to the on... events in Activity or ListActivity that you override for lifecycle and other functionality hooks.

 

2. 覆盖来自父类的一些方法。要覆盖的超类方法以on开头,例如,onDraw(),onMeasure()和onKeyDown()。这类似于Activity或ListActivity里的on...事件,你可以覆盖它们用于生命周期和其它功能拦截。

 

3. Use your new extension class. Once completed, your new extension class can be used in place of the view upon which it was based.

 

3. 使用你的新扩展类。一旦完成,你的新扩展类可以被用于作为基类的视图的位置上。

 

-------------------------------

 

Tip: Extension classes can be defined as inner classes inside the activities that use them. This is useful because it controls access to them but isn't necessary (perhaps you want to create a new public View for wider use in your application).

 

提示:扩展类可以被定义为使用它们的活动中的内部类。这是有用的,因为它控制对它们的访问但不是必需的(可能你希望创建一个新的public的View以扩大你的应用程序的使用范围)。

 

-------------------------------

 

-------------------------------

 

Fully Customized Components

 

完全自定义组件

 

Fully customized components can be used to create graphical components that appear however you wish. Perhaps a graphical VU meter that looks like an old analog gauge, or a sing-a-long text view where a bouncing ball moves along the words so you can sing along with a karaoke machine. Either way, you want something that the built-in components just won't do, no matter how you combine them.

 

完全自定义的组件可以被使用以创建以你所希望的任意样子显示的图形组件。可能一个图形化的VU表盘(注:Volume Unit,VU表,指一种音量测量仪器)看起来想一个旧式的模拟仪表,或者是一个单行的长文本视图,在那里一个弹跳球沿着文字移动使你可以跟着一个卡拉OK机器唱歌。无论是哪种方式,你想要一些内建组件就是无法做到的东西,不管你如何组合它们。

 

Fortunately, you can easily create components that look and behave in any way you like, limited perhaps only by your imagination, the size of the screen, and the available processing power (remember that ultimately your application might have to run on something with significantly less power than your desktop workstation).

 

幸运地,你可以轻易创建组件,它以你想要的方式表现和行为,只可能受到你的想象力,屏幕大小和可用的处理电量的限制(记住最终你可能不得不运行在一些比你的桌面工作站显著低功耗的东西上)

 

To create a fully customized component:

 

为了创建一个完全自定义组件:

 

1. The most generic view you can extend is, unsurprisingly, View, so you will usually start by extending this to create your new super component.

 

1. 毋庸置疑,你可以扩展的最通用的视图是View,所以你将通常通过扩展它开始创建你的新的超类组件。

 

2. You can supply a constructor which can take attributes and parameters from the XML, and you can also consume your own such attributes and parameters (perhaps the color and range of the VU meter, or the width and damping of the needle, etc.)

 

2. 你可以提供一个构造函数,它可以从XML中得到属性和参数,并且你还可以恢复你自己的这些属性和参数(可能是VU表的颜色和范围,或者是指针的宽度和阻尼,等等)

 

3. You will probably want to create your own event listeners, property accessors and modifiers, and possibly more sophisticated behavior in your component class as well.

 

3. 你将很可能还希望在你的组件类内创建你自己的事件监听器,属性访问器和修改器,甚至可能更复杂的行为。

 

4. You will almost certainly want to override onMeasure() and are also likely to need to override onDraw() if you want the component to show something. While both have default behavior, the default onDraw() will do nothing, and the default onMeasure() will always set a size of 100x100 — which is probably not what you want.

 

4. 你将几乎肯定希望覆盖onMeasure()同时还可能需要覆盖onDraw()如果你希望组件显示一些东西。虽然两者都拥有默认行为,但是默认的onDraw()将什么都不做,并且默认的onMeasure()将总是设置大小为100x100——它可能不是你想要的。

 

5. Other on... methods may also be overridden as required.

 

5. 其它on...方法也可能在需要时被覆盖。

 

Extend onDraw() and onMeasure()

 

扩展onDraw()和onMeasure()

 

The onDraw() method delivers you a Canvas upon which you can implement anything you want: 2D graphics, other standard or custom components, styled text, or anything else you can think of.

 

onDraw()方法传递你一个Canvas,在它上面你可以实现你想要的任何事情:二维图形,其它标准或自定义组件,样式化文本,或其它任意你可以想象的东西。

 

-------------------------------

 

Note: This does not apply to 3D graphics. If you want to use 3D graphics, you must extend SurfaceView instead of View, and draw from a separate thread. See the GLSurfaceViewActivity sample for details.

 

注意:它不应用于三维图形。如果你希望使用三维图形,你必须继承SurfaceView而非View,并且从一个单独的线程中绘画。详细请见GLSurfaceViewActivity示例。

 

-------------------------------

 

onMeasure() is a little more involved. onMeasure() is a critical piece of the rendering contract between your component and its container. onMeasure() should be overridden to efficiently and accurately report the measurements of its contained parts. This is made slightly more complex by the requirements of limits from the parent (which are passed in to the onMeasure() method) and by the requirement to call the setMeasuredDimension() method with the measured width and height once they have been calculated. If you fail to call this method from an overridden onMeasure() method, the result will be an exception at measurement time.

 

onMeasure()较少被调用。onMeasure()是你的组件和它的容器之间协作的渲染的关键部分。onMeasure()应该被覆盖以有效和准确地报告它容纳的部分的度量。通过要求来自父容器的limits(它被传递进onMeasure()方法),并且通过要求用测量过的宽和高调用setMeasuredDimension()一旦它们已经被重新计算,使得这个过程稍微更复杂些。如果你从一个覆盖的onMeasure()中调用此方法时失败,结果将是在一个度量期的异常。

 

At a high level, implementing onMeasure() looks something like this:

 

作为高层次,实现onMeasure()像这样看一些事情:

 

1. The overridden onMeasure() method is called with width and height measure specifications (widthMeasureSpec and heightMeasureSpec parameters, both are integer codes representing dimensions) which should be treated as requirements for the restrictions on the width and height measurements you should produce. A full reference to the kind of restrictions these specifications can require can be found in the reference documentation under View.onMeasure(int, int) (this reference documentation does a pretty good job of explaining the whole measurement operation as well).

 

1. 覆盖的onMeasure()方法用宽和高度量规范来调用(widthMeasureSpec和heightMeasureSpec参数,它们都是整型号码代表尺寸),它们应该被视为你应该产生的宽和高度量的限制要求。指向这些规范可以获取的限制类型的完全参考可以在View.onMeasure(int, int)下的参考文档中找到(同时这个参考文档做了一件极好的工作,解释了整个度量操作)。

 

2. Your component's onMeasure() method should calculate a measurement width and height which will be required to render the component. It should try to stay within the specifications passed in, although it can choose to exceed them (in this case, the parent can choose what to do, including clipping, scrolling, throwing an exception, or asking the onMeasure() to try again, perhaps with different measurement specifications).

 

2. 你的组件的onMeasure()方法应该计算渲染组件所需的度量宽度和高度。它应该尝试停留在传入的规范内,虽然它可以选择超出它们(在这种情况下,父对象可以选择做什么,包括剪裁,滚动,抛出异常,或询问onMeasure()以重新尝试,可能使用不同的度量规范)。

 

3. Once the width and height are calculated, the setMeasuredDimension(int width, int height) method must be called with the calculated measurements. Failure to do this will result in an exception being thrown.

 

3. 一旦宽和高被计算,setMeasuredDimension(int width, int height)方法必须用被计算的度量来调用。执行失败将导致异常被抛出。

 

Here's a summary of some of the other standard methods that the framework calls on views:

 

这里是其它一些框架调用在视图上的标准方法的总结:

 

-------------------------------

 

Category Methods Description

 

分类 方法 描述

 

Creation

 

创建

 

* Constructors There is a form of the constructor that are called when the view is created from code and a form that is called when the view is inflated from a layout file. The second form should parse and apply any attributes defined in the layout file.

 

* 构造函数:有一个构造函数形式在视图从代码中创建时被调用,而有一个形式是在视图从一个布局文件中被解压时调用。第二个形式应该解析和应用定义在布局文件内的任意属性。

 

* onFinishInflate() Called after a view and all of its children has been inflated from XML.

 

* onFinishInflate():在一个视图和它的所有子视图已经从XML解压后被调用。

 

Layout

 

布局

 

* onMeasure(int, int) Called to determine the size requirements for this view and all of its children.

 

* onMeasure(int, int):调用以决定这个视图和它的所有子视图需要的大小。

 

* onLayout(boolean, int, int, int, int) Called when this view should assign a size and position to all of its children.

 

* onLayout(boolean, int, int, int, int):当这个视图应该赋予一个大小和位置到它的所有子视图时被调用。

 

* onSizeChanged(int, int, int, int) Called when the size of this view has changed.

 

* onSizeChanged(int, int, int, int):当这个视图的大小已经改变时被调用。

 

Drawing

 

绘画

 

* onDraw(Canvas) Called when the view should render its content.

 

* onDraw(Canvas):当视图应该渲染它的内容时被调用。

 

Event processing

 

事件处理

 

* onKeyDown(int, KeyEvent) Called when a new key event occurs.

 

* onKeyDown(int, KeyEvent):当一个新的键盘事件发生时被调用。

 

* onKeyUp(int, KeyEvent) Called when a key up event occurs.

 

* onKeyUp(int, KeyEvent):当一个键盘弹起事件发生时被调用。

 

* onTrackballEvent(MotionEvent) Called when a trackball motion event occurs.

 

* onTrackballEvent(MotionEvent):当一个轨迹球动作事件发生时被调用。

 

* onTouchEvent(MotionEvent) Called when a touch screen motion event occurs.

 

* onTouchEvent(MotionEvent):当一个触碰屏幕动作事件发生时被调用。

 

Focus

 

焦点

 

* onFocusChanged(boolean, int, Rect) Called when the view gains or loses focus.

 

* onFocusChanged(boolean, int, Rect):当视图获取或失去焦点时被调用。

 

* onWindowFocusChanged(boolean) Called when the window containing the view gains or loses focus.

 

* onWindowFocusChanged(boolean):当包含视图的窗口获取或失去焦点时被调用。

 

Attaching

 

依附

 

* onAttachedToWindow() Called when the view is attached to a window.

 

* onAttachedToWindow():当视图被依附到一个窗口时被调用。

 

* onDetachedFromWindow() Called when the view is detached from its window.

 

* onDetachedFromWindow():当视图从它的窗口中解除依附时被调用。

 

* onWindowVisibilityChanged(int) Called when the visibility of the window containing the view has changed.

 

* onWindowVisibilityChanged(int):当包含视图的窗口的可见性已经被改变时被调用。

 

-------------------------------

 

A Custom View Example

 

一个自定义视图示例

 

The CustomView sample in the API Demos provides an example of a customized View. The custom View is defined in the LabelView class.

 

API演示的CustomView示例提供一个自定义View的例子。自定义View被定义在LabelView类中。

 

The LabelView sample demonstrates a number of different aspects of custom components:

 

LabelView示例演示自定义组件的很多不同方面:

 

* Extending the View class for a completely custom component.

 

* 扩展View类以获得完全自定义组件

 

* Parameterized constructor that takes the view inflation parameters (parameters defined in the XML). Some of these are passed through to the View superclass, but more importantly, there are some custom attributes defined and used for LabelView.

 

* 取得视图解压参数(定义在XML内的参数)的被参数化的构造函数。这些参数中有些被传递到View超类,但更重要地,有一些自定义属性被定义和用于LabelView。

 

* Standard public methods of the type you would expect to see for a label component, for example setText(), setTextSize(), setTextColor() and so on.

 

* 对于一个标签组件来说你期望看到的类型的标准public方法,例如setText(),setTextSize(),setTextColor()等等。

 

* An overridden onMeasure method to determine and set the rendering size of the component. (Note that in LabelView, the real work is done by a private measureWidth() method.)

 

* 一个覆盖的onMeasure方法以决定和设置组件的渲染大小。(注意在LabelView里,真正的工作是由私有的measureWidth()完成。)

 

* An overridden onDraw() method to draw the label onto the provided canvas.

 

* 一个覆盖的onDraw()方法用于在提供的画布上绘画标签。

 

You can see some sample usages of the LabelView custom View in custom_view_1.xml from the samples. In particular, you can see a mix of both android: namespace parameters and custom app: namespace parameters. These app: parameters are the custom ones that the LabelView recognizes and works with, and are defined in a styleable inner class inside of the samples R resources definition class.

 

你可以在来自示例的custom_view_1.xml中看到LabelView自定义视图的示例用法。特别地,你可以看到android:名字空间参数以及app:名字空间参数的混合。这些app:参数是LabelView认识并且处理的自定义参数,而且定义在示例的R资源定义类内的可样式化内部类中。

 

-------------------------------

 

Compound Controls

 

复合控件

 

If you don't want to create a completely customized component, but instead are looking to put together a reusable component that consists of a group of existing controls, then creating a Compound Component (or Compound Control) might fit the bill. In a nutshell, this brings together a number of more atomic controls (or views) into a logical group of items that can be treated as a single thing. For example, a Combo Box can be thought of as a combination of a single line EditText field and an adjacent button with an attached PopupList. If you press the button and select something from the list, it populates the EditText field, but the user can also type something directly into the EditText if they prefer.

 

如果你不希望创建一个完全自定义组件,而是指望把一个包含一组现存控件的可重用组件放在一起,那么创建一个复合组件(或复合控件)可能更符合要求。简单而言,它把一些更原子的控件(或视图)一起放进一个可以被视为单一东西的条目逻辑分组。例如,一个组合框可以被想象为单行EditText域和一个被PopupList依附的邻接按钮的组合。如果你按下按钮并且从列表中选择一些东西,那么它填充EditText域,但用户也可以直接输入一些东西进EditText如果他们喜欢的话。

 

In Android, there are actually two other Views readily available to do this: Spinner and AutoCompleteTextView, but regardless, the concept of a Combo Box makes an easy-to-understand example.

 

在Android内,实际上有另外两个View可以轻松做到这点:Spinner和AutoCompleteTextView,但无论如何,Combo框的概念造就一个易于理解的示例。

 

To create a compound component:

 

为了创建一个复合组件:

 

1. The usual starting point is a Layout of some kind, so create a class that extends a Layout. Perhaps in the case of a Combo box we might use a LinearLayout with horizontal orientation. Remember that other layouts can be nested inside, so the compound component can be arbitrarily complex and structured. Note that just like with an Activity, you can use either the declarative (XML-based) approach to creating the contained components, or you can nest them programmatically from your code.

 

1. 通常的起点是一些类型的Layout,那样会创建扩展自一个Layout的类。可能在一个Combo框的情况下我们可能使用一个带有水平方向的LinearLayout。记住其他布局可能嵌套其中,所以复合组件可以是任意地复杂和被构造。注意就像使用一个Activity那样,你可以使用声明式(基于XML)的方法创建包含的组件,或者你可以用程序手段从你的代码中嵌套它们。

 

2. In the constructor for the new class, take whatever parameters the superclass expects, and pass them through to the superclass constructor first. Then you can set up the other views to use within your new component; this is where you would create the EditText field and the PopupList. Note that you also might introduce your own attributes and parameters into the XML that can be pulled out and used by your constructor.

 

2. 在新类的构造函数中,传入超类期待的任意参数,并且首先传递它们到超类的构造函数。然后你可以配置其他视图以在你的新组件内使用;这是你应该创建EditText域和PopupList的地方。注意你还可能引入你自己的属性和参数放进可能被拉出和被你的构造函数使用的XML。

 

3. You can also create listeners for events that your contained views might generate, for example, a listener method for the List Item Click Listener to update the contents of the EditText if a list selection is made.

 

3. 你还可以为你所包含的视图可能产生的事件创建监听器,例如,一个用于List条目的点击监听器的监听器方法将更新EditText的内容如果作出一个列表选择。

 

4. You might also create your own properties with accessors and modifiers, for example, allow the EditText value to be set initially in the component and query for its contents when needed.

 

4. 你还可能用访问器和修改器创建你自己的属性,例如,允许EditText的组件内的值最初被设置并且在需要时查询它的内容。

 

5. In the case of extending a Layout, you don't need to override the onDraw() and onMeasure() methods since the layout will have default behavior that will likely work just fine. However, you can still override them if you need to.

 

5. 在扩展一个Layout的情况下,你不需要覆盖onDraw()和onMeasure()方法,因为布局将拥有默认行为,它将可能工作得很好。然而,你仍然可以覆盖它们如果你需要这样做。

 

6. You might override other on... methods, like onKeyDown(), to perhaps choose certain default values from the popup list of a combo box when a certain key is pressed.

 

6. 你可能覆盖其它on...方法,像onKeyDown(),以便有可能从一个组合框的弹出列表中选择某个默认值,当某个按键被按下。

 

To summarize, the use of a Layout as the basis for a Custom Control has a number of advantages, including:

 

为了总结,使用Layout作为自定义控件的基本(注:基类?)具有很多好处,包括:

 

* You can specify the layout using the declarative XML files just like with an activity screen, or you can create views programmatically and nest them into the layout from your code.

 

* 你可以使用声明XML文件指定布局,就像带有一个活动屏幕,或者你可以用程序创建视图并且从你的代码中把它们嵌套进布局。

 

* The onDraw() and onMeasure() methods (plus most of the other on... methods) will likely have suitable behavior so you don't have to override them.

 

* onDraw()和onMeasure()方法(以及其它大多数on...方法)将可能拥有合适的行为所以你不必覆盖它们。

 

* In the end, you can very quickly construct arbitrarily complex compound views and re-use them as if they were a single component.

 

* 在结束的时候,你可以非常快地构造任意复杂的复合视图并且重用它们,好像它们真的是一个单一组件。

 

Examples of Compound Controls

 

复合控件示例

 

In the API Demos project that comes with the SDK, there are two List examples — Example 4 and Example 6 under Views/Lists demonstrate a SpeechView which extends LinearLayout to make a component for displaying Speech quotes. The corresponding classes in the sample code are List4.java and List6.java.

 

在附带在SDK中的API演示工程中,有两个List示例——在视图/列表演示下的示例4和示例6演示一个扩展自LinearLayout的SpeechView制作出一个组件用于显示语音引用。示例代码中对应的类是List4.java和List6.java。

 

-------------------------------

 

Modifying an Existing View Type

 

修改一个现存View类型

 

There is an even easier option for creating a custom View which is useful in certain circumstances. If there is a component that is already very similar to what you want, you can simply extend that component and just override the behavior that you want to change. You can do all of the things you would do with a fully customized component, but by starting with a more specialized class in the View hierarchy, you can also get a lot of behavior for free that probably does exactly what you want.

 

有一个甚至更简单的选择来创建一个在某种环境下有用的自定义View。如果有一个组件对于你想要的东西来说已经非常相似,那么你可以简单地扩展那个组件并且仅覆盖你希望改变的行为。你可以做你将要处理一个完全定制组件的所有事情,但通过从View层级中一个更特化的类开始,你还可以免费获得很多很可能正好做你想做的事情的行为。

 

For example, the SDK includes a NotePad application in the samples. This demonstrates many aspects of using the Android platform, among them is extending an EditText View to make a lined notepad. This is not a perfect example, and the APIs for doing this might change from this early preview, but it does demonstrate the principles.

 

例如,SDK在示例中包含一个记事本应用程序。它演示使用Android平台的很多方面,在它们之间包括扩展一个EditText的View类以制作单行簿式的记事本。这不是一个极好的例子,而用于做这件事的API可能从前期预览版发生变化,但它演示这个原则。

 

If you haven't done so already, import the NotePad sample into Eclipse (or just look at the source using the link provided). In particular look at the definition of MyEditText in the NoteEditor.java file.

 

如果你尚未做到这样,请导入记事本示例进Eclipse(或只看一下使用链接提供的源码)。特别地看一下NoteEditor.java文件内MyEditText的定义。

 

Some points to note here

 

这里一些要注意的点

 

1. The Definition

 

1. 定义

 

The class is defined with the following line:

 

类用以下代码行来定义:

 

public static class MyEditText extends EditText

 

* It is defined as an inner class within the NoteEditor activity, but it is public so that it could be accessed as NoteEditor.MyEditText from outside of the NoteEditor class if desired.

 

* 它被定义为一个NoteEditor活动的内部类,但它是public,所以如果需要的话它可以作为NoteEditor.MyEditText从NoteEditor类的外部访问它。

 

* It is static, meaning it does not generate the so-called "synthetic methods" that allow it to access data from the parent class, which in turn means that it really behaves as a separate class rather than something strongly related to NoteEditor. This is a cleaner way to create inner classes if they do not need access to state from the outer class, keeps the generated class small, and allows it to be used easily from other classes.

 

* 它是static的,意味着它不生成允许访问来自父类数据的所谓“合成方法”,放过来意味着它真正地作为一个单独的类来行为而非一些强关联到NoteEditor的东西。这是较干净的方式创建内部类,如果它们不需要访问来自外部类的状态,保持生成类较小,并且允许它容易被其它类使用。

 

* It extends EditText, which is the View we have chosen to customize in this case. When we are finished, the new class will be able to substitute for a normal EditText view.

 

* 它扩展EditText,EditText是在这里我们选择自定义的View。当我们完成了,新类将可以代替一个普通的EditText视图。

 

2. Class Initialization

 

2. 类初始化

 

As always, the super is called first. Furthermore, this is not a default constructor, but a parameterized one. The EditText is created with these parameters when it is inflated from an XML layout file, thus, our constructor needs to both take them and pass them to the superclass constructor as well.

 

如往常那样,super(注:这里指超类的构造函数)被首先调用,更进一步,它不是一个默认的函数,而是带有参数的。EditText在它从XML布局文件中被解压时用这些参数被创建,这样,我们的构造函数既需要获取它们,也需要传递它们到超类的构造函数。

 

3. Overridden Methods

 

3. 被覆盖的方法

 

In this example, there is only one method to be overridden: onDraw() — but there could easily be others needed when you create your own custom components.

 

在这个示例中,只有一个方法要被覆盖:onDraw()——但在你创建你自己的组件时可能有其它需要的东西。

 

For the NotePad sample, overriding the onDraw() method allows us to paint the blue lines on the EditText view canvas (the canvas is passed into the overridden onDraw() method). The super.onDraw() method is called before the method ends. The superclass method should be invoked, but in this case, we do it at the end after we have painted the lines we want to include.

 

对于记事本示例,覆盖onDraw()允许我们在EditText视图画布上绘画蓝色线(画布被传递进覆盖的onDraw()方法)。super.onDraw()方法在方法结束前被调用。超类方法应该被调用,但在这种情况下,我们在最后我们已经绘画我们希望包含的线之后执行它。

 

4. Use the Custom Component

 

4. 使用自定义组件

 

We now have our custom component, but how can we use it? In the NotePad example, the custom component is used directly from the declarative layout, so take a look at note_editor.xml in the res/layout folder.

 

我们现在拥有我们自己的自定义组件,但我们可以如何使用它?在记事本示例中,自定义组件被直接从声明的布局中使用,所以请看一下res/layout文件夹下的note_editor.xml。

 

-------------------------------

 

<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" />

 

-------------------------------

 

* The custom component is created as a generic view in the XML, and the class is specified using the full package. Note also that the inner class we defined is referenced using the NoteEditor$MyEditText notation which is a standard way to refer to inner classes in the Java programming language.

 

* 自定义组件被创建作为XML中一个通常的视图,并且该类使用完全包名来指定。还要注意我们定义的内部类使用NoteEditor$MyEditText符号来引用,它是在Java编程语言中引用内部类的标准方法。

 

If your custom View component is not defined as an inner class, then you can, alternatively, declare the View component with the XML element name, and exclude the class attribute. For example:

 

如果你的自定义View组件不是定义为一个内部内,那么你可以可选地用XML元素名声明View组件,并且排除class属性。例如:

 

-------------------------------

 

<com.android.notepad.MyEditText

  id="@+id/note"

  ... />

 

-------------------------------

 

Notice that the MyEditText class is now a separate class file. When the class is nested in the NoteEditor class, this technique will not work.

 

注意MyEditText类现在是一个单独的类文件。当该类是嵌套在NoteEditor类内时,这种技术将不能工作。

 

* The other attributes and parameters in the definition are the ones passed into the custom component constructor, and then passed through to the EditText constructor, so they are the same parameters that you would use for an EditText view. Note that it is possible to add your own parameters as well, and we will touch on this again below.

 

* 定义中其它属性和参数是传递进自定义组件构造函数的参数,然后传递到EditText构造函数,所以它们是和你用于EditText视图的相同参数。注意也可以添加你自己的参数,并且我们将在下面再次触碰它。

 

And that's all there is to it. Admittedly this is a simple case, but that's the point — creating custom components is only as complicated as you need it to be.

 

对于这个例子来说就完成了。诚然这是一个简单例子,但提到点上——创建自定义组件只是如你所需那样地复杂。

 

A more sophisticated component may override even more on... methods and introduce some of its own helper methods, substantially customizing its properties and behavior. The only limit is your imagination and what you need the component to do.

 

一个更复杂的组件可能覆盖更多on...方法并且引入一些它自己的辅助方法,大幅地自定义它的属性和行为。唯一的限制是你的想象力以及你需要组件做什么。

 

Except as noted, this content is licensed under Apache 2.0. For details and restrictions, see the Content License.

 

除特别说明外,本文在Apache 2.0下许可。细节和限制请参考内容许可证。

 

Android 4.0 r1 - 09 Dec 2011 11:54

 

-------------------------------

 

Portions of this page are modifications based on work created and shared by the Android Open Source Project and used according to terms described in the Creative Commons 2.5 Attribution License.

 

(此页部分内容基于Android开源项目,以及使用根据创作公共2.5来源许可证描述的条款进行修改)


分享到:
评论

相关推荐

    Delphi7中文帮助 之创建自定义组件

    Delphi7中文帮助之创建自定义组件部分(SWF格式) 已经完成了两个章节的翻译,现发布Flash版本,供大家先睹为快,可以在这里查看和下载(需要Flash插件),请其他章节的翻译者抓进时间,切勿延期交付。 想...

    alexa_media_player:这是一个自定义组件,允许使用非官方的Alexa API在Home Assistant中控制Amazon Alexa设备

    这是一个自定义组件,允许使用非官方的Alexa API在控制Amazon Alexa设备。 请注意,这模仿了Alexa应用程序,但Amazon可能会随时切断访问权限。 它能做什么: 允许控制具有以下功能的Amazon Echo产品作为家庭辅助...

    SimpleLocalization:用于使用Google Tables本地化Unity项目的插件。 它可以翻译Text组件,TextMeshPro,并在自定义脚本中接收本地化的字符串。 具有灵活的定制

    产品特点自动翻译Text,TextMeshPro组件运行时更改语言而无需重新启动应用程序使用不同的Google Tables开发和发行版本能够自定义翻译下载(自动,手动) 能够在构建项目之前下载翻译快速测试翻译的功能翻译验证如何...

    vue-storybook:自定义Vue单个文件组件的块

    故事书 Vue单个文件组件的自定义块,... Webpack加载器+帮助程序脚本,可让您使用自定义的块修饰已存在的Vue单个文件组件(SFC),该块会自动翻译成风格的故事。 你好世界的例子 回购: : &lt; my-button : disabled

    react-scrollbars-custom:最好的React自定义滚动条组件

    本机浏览器的滚动行为-它不模拟滚动,仅显示自定义滚动条,仍以本机滚动 跨浏览器和跨平台-无关紧要的地方和方式,滚动条在各处看起来都一样 终极性能-60 FPS(使用RAF)和高度优化的代码 无需额外的样式表-现成的...

    phaser3-custom-build:创建您自己的自定义Phaser 3版本并减少捆绑包大小数百KB

    其他捆绑软件,例如Parcel,也可以使用,但是您需要将本指南翻译成各自的格式。 要记住的重要一点是,如webpack中所定义的,Phaser模块入口点控制着公开API的整个结构。 也就是说,它包含的所有内容都可以在Phaser...

    CmsEasy可视化编辑商城系统 v7.2.3

    商城模块自定义商品筛选支持选定栏目、分类、专题组合筛选商品;商品项自定义支持任意个商品自定义项价格,可由自定义项进行加减乘除运算;... 不限制语言数量任意添加语言翻译需手动翻译网站内容后录入到对应

    Advanced Installer Architect 14.x Patch

    5、ODBC 驱动程序、数据源和翻译程序 6、.NET 和 Win32 程序集 7、服务 8、文件关联、MIME 类型 9、文件、文件夹、注册表项和值的访问权限 - 搜索、下载并安装运行环境 - 在模块和组件中组织您的应用程序 - ...

    Chakra UI Vue-:high_voltage:轻巧且可自定义的组件库,可帮助您快速构建可访问的Vue应用程序和站点。-Vue.js开发

    轻松构建可扩展且可访问的...转到此处=&gt; https://vue.chakra-ui.com中文文档翻译Github问题功能易于设计:Chakra UI包含一组布局组件,如CBox和CStack,可轻松通过传递道具来对组件进行样式设置。 了解更多灵活和组合

    csw5.0中文分词组件

    互联网信息检索、数据库信息查询、智能聊天机器人、文本校对、自动翻译、 自动摘要、自动分类及信息加工处理等各个领域。 二、本组件特点: 1.适应性强 本组全部件采用ANSI标准C++开发,可广泛应用于当今的操作...

    Wicket 8.X开发文档(中文翻译+英文原版)

    23.使用Wicket进行测试驱动开发 23.1。实用工具类WicketTester 23.2。测试Wicket表单 23.3。使用TagTester测试标记 23.4。摘要 24.使用Wicket和Spring测试驱动开发 24.1。配置运行时环境 24.2。配置基于JUnit的集成...

    vue-credit-card-用于信用卡输入,遮罩和预览的Vue组件-Vue.js开发

    本地化(i18n)(欢迎所有翻译)卡预览隐藏敏感信息卡输入掩码可轻松自定义验证程序入门从'@ fracto / vue-credit-card'导入通用导入VueCreditCard; / *全局使用* / Vue.use(VueCreditCard); / *本地组件* /导出...

    FLEX企业应用开发实战.part1

     2.5.4 使用ActionScript创建自定义组件  2.6 异步调用  2.6.1 异步调用导致模型数据不一致  2.6.2 异步调用导致用户反复(误)操作  2.7 小结 第3章 Flex企业应用开发中的主要元素  3.1 企业应用的特点...

    FLEX企业应用开发实战.part2

     2.5.4 使用ActionScript创建自定义组件  2.6 异步调用  2.6.1 异步调用导致模型数据不一致  2.6.2 异步调用导致用户反复(误)操作  2.7 小结 第3章 Flex企业应用开发中的主要元素  3.1 企业应用的特点...

    polylang-supertext:Wordpress Polylang多语言附加组件的超文本插件

    翻译过程超文本可以翻译内容,标题,摘录,图像标题,简码参数和自定义字段。 只需订购翻译,而不用创建新页面。 您将获得服务,价格和截止日期。 为您选择合适的一个。 完成后,翻译将自动插入新页面或发布到...

    okapi-worldserver-components:基于Okapi框架的WorldServer SDK组件

    适用于WorldServer的Okapi组件该存储库包含使用WorldServer SDK(WSSDK)开发的自定义WorldServer组件,这些组件基于作为开放源代码一部分可用的过滤器和其他组件。 当前,此存储库包含: 过滤器,包括IDML JSON格式...

    搜狗拼音输入法6.8

    表情、符号、酷字等功能以组件形式,自定义添加 中英文、简繁体、全双拼等切换功能以挂件形式可悬浮在桌面上 新增大五码功能,在台服游戏等进程中上屏再无乱码;智能模糊音策略优化 输入法修复器逻辑优化 手写组件...

    详解k8s组件Ingress边缘路由器并落地到微服务-kubernetes

    Ingress英文翻译进入;进入权;进食,更准确的讲就是入口,即外部流量进入k8s集群必经之口。这到大门到底有什么作用?我们如何使用Ingress?k8s又是如何进行服务发现的呢?先看一张图:虽然k8s集群内部署的pod、server...

    atomic_calendar:带有Lovelace的家庭助理的自定义日历卡

    自定义颜色和不同日历的设置,自定义字体大小,每个文本和每行的颜色 包含所有翻译,可以在设置中配置很少的单词 兼容全天和全天活动 在两种模式之间快速切换,或将其中一种设置为默认模式 事件模式: 以不同的...

    TexTra-crx插件

    textra chrome addon 在浏览器“Google Chrome”的附加组件中, 它是翻译文本和字典的软件。 翻译是由“自动翻译”的“自动翻译”执行的翻译。 您可以添加自己的自定义翻译和字典。 ...

Global site tag (gtag.js) - Google Analytics