ETL,Extraction-Transformation-Loading的缩写,中文名称为数据提取、转换和加载。
数据抽取
ETL工具有:OWB(Oracle Warehouse Builder)、ODI(Oracle Data Integrator)、Informatic PowerCenter、AICloudETL、DataStage、Repository Explorer、Beeload、Kettle、DataSpider
ETL负责将分布的、异构数据源中的数据如关系数据、平面数据文件等抽取到临时中间层后进行清洗、转换、集成,最后加载到数据仓库或数据集市中,成为联机分析处理、数据挖掘的基础。 ETL一词较常出现在数据仓库,但其对象并不局限于数据仓库。 ETL是数据仓库中的非常重要的一环。它是承前启后的必要的一步。相对于关系数据库,数据仓库技术没有严格的数学理论基础,它更面向实际工程应用。所以从工程应用的角度来考虑,按着物理数据模型的要求加载数据并对数据进行一些系列处理,处理过程与经验直接相关,同时这部分的工作直接关系数据仓库中数据的质量,从而影响到联机分析处理和数据挖掘的结果的质量。 数据仓库是一个独立的数据环境,需要通过抽取过程将数据从联机事务处理环境、外部数据源和脱机的数据存储介质导入到数据仓库中;在技术上,ETL主要涉及到关联、转换、增量、调度和监控等几个方面;数据仓库系统中数据不要求与联机事务处理系统中数据实时同步,所以ETL可以定时进行。但多个ETL的操作时间、顺序和成败对数据仓库中信息的有效性至关重要。 ETL(Extract-Transform-Load的缩写,即数据抽取、转换、装载的过程)作为BI/DW(Business Intelligence)的核心和灵魂,能够按照统一的规则集成并提高数据的价值,是负责完成数据从数据源向目标数据仓库转化的过程,是实施数据仓库的重要步骤。如果说数据仓库的模型设计是一座大厦的设计蓝图,数据是砖瓦的话,那么ETL就是建设大厦的过程。在整个项目中最难部分是用户需求分析和模型设计,而ETL规则设计和实施则是工作量最大的,约占整个项目的60%~80%,这是国内外从众多实践中得到的普遍共识。 ETL是数据抽取(Extract)、清洗(Cleaning)、转换(Transform)、装载(Load)的过程。是构建数据仓库的重要一环,用户从数据源抽取出所需的数据,经过数据清洗,最终按照预先定义好的数据仓库模型,将数据加载到数据仓库中去。 信息是现代企业的重要资源,是企业运用科学管理、决策分析的基础。目前,大多数企业花费大量的资金和时间来构建联机事务处理OLTP的业务系统和办公自动化系统,用来记录事务处理的各种相关数据。据统计,数据量每2~3年时间就会成倍增长,这些数据蕴含着巨大的商业价值,而企业所关注的通常只占在总数据量的2%~4%左右。因此,企业仍然没有最大化地利用已存在的数据资源,以致于浪费了更多的时间和资金,也失去制定关键商业决策的最佳契机。于是,企业如何通过各种技术手段,并把数据转换为信息、知识,已经成了提高其核心竞争力的主要瓶颈。而ETL则是主要的一个技术手段。如何正确选择ETL工具?如何正确应用ETL? 目前,ETL工具的典型代表有:Informatica、Datastage、OWB、微软DTS、Beeload、Kettle…… 开源的工具有eclips的etl插件。cloveretl. 数据集成:快速实现ETL ETL的质量问题具体表现为正确性、完整性、一致性、完备性、有效性、时效性和可获取性等几个特性。而影响质量问题的原因有很多,由系统集成和历史数据造成的原因主要包括:业务系统不同时期系统之间数据模型不一致;业务系统不同时期业务过程有变化;旧系统模块在运营、人事、财务、办公系统等相关信息的不一致;遗留系统和新业务、管理系统数据集成不完备带来的不一致性。 实现ETL,首先要实现ETL转换的过程。它可以集中地体现为以下几个方面: 空值处理 可捕获字段空值,进行加载或替换为其他含义数据,并可根据字段空值实现分流加载到不同目标库。 规范化数据格式 可实现字段格式约束定义,对于数据源中时间、数值、字符等数据,可自定义加载格式。 拆分数据 依据业务需求对字段可进行分解。例,主叫号 861082585313-8148,可进行区域码和电话号码分解。 验证数据正确性 可利用Lookup及拆分功能进行数据验证。例如,主叫号861082585313-8148,进行区域码和电话号码分解后,可利用Lookup返回主叫网关或交换机记载的主叫地区,进行数据验证。 数据替换 对于因业务因素,可实现无效数据、缺失数据的替换。 Lookup 查获丢失数据 Lookup实现子查询,并返回用其他手段获取的缺失字段,保证字段完整性。 建立ETL过程的主外键约束 对无依赖性的非法数据,可替换或导出到错误数据文件中,保证主键唯一记录的加载。 为了能更好地实现ETL,笔者建议用户在实施ETL过程中应注意以下几点: 第一,如果条件允许,可利用数据中转区对运营数据进行预处理,保证集成与加载的高效性; 第二,如果ETL的过程是主动“拉取”,而不是从内部“推送”,其可控性将大为增强; 第三,ETL之前应制定流程化的配置管理和标准协议; 第四,关键数据标准至关重要。目前,ETL面临的最大挑战是当接收数据时其各源数据的异构性和低质量。以电信为例,A系统按照统计代码管理数据,B系统按照账目数字管理,C系统按照语音ID管理。当ETL需要对这三个系统进行集成以获得对客户的全面视角时,这一过程需要复杂的匹配规则、名称/地址正常化与标准化。而ETL在处理过程中会定义一个关键数据标准,并在此基础上,制定相应的数据接口标准。 ETL过程在很大程度上受企业对源数据的理解程度的影响,也就是说从业务的角度看数据集成非常重要。一个优秀的ETL设计应该具有如下功能: 管理简单;采用元数据方法,集中进行管理;接口、数据格式、传输有严格的规范;尽量不在外部数据源安装软件;数据抽取系统流程自动化,并有自动调度功能;抽取的数据及时、准确、完整;可以提供同各种数据系统的接口,系统适应性强;提供软件框架系统,系统功能改变时,应用程序很少改变便可适应变化;可扩展性强。 数据模型:标准定义数据 合理的业务模型设计对ETL至关重要。数据仓库是企业唯一、真实、可靠的综合数据平台。数据仓库的设计建模一般都依照三范式、星型模型、雪花模型,无论哪种设计思想,都应该最大化地涵盖关键业务数据,把运营环境中杂乱无序的数据结构统一成为合理的、关联的、分析型的新结构,而ETL则会依照模型的定义去提取数据源,进行转换、清洗,并最终加载到目标数据仓库中。 模型的重要之处在于对数据做标准化定义,实现统一的编码、统一的分类和组织。标准化定义的内容包括:标准代码统一、业务术语统一。ETL依照模型进行初始加载、增量加载、缓慢增长维、慢速变化维、事实表加载等数据集成,并根据业务需求制定相应的加载策略、刷新策略、汇总策略、维护策略。 元数据:拓展新型应用 对业务数据本身及其运行环境的描述与定义的数据,称之为元数据(metadata)。元数据是描述数据的数据。从某种意义上说,业务数据主要用于支持业务系统应用的数据,而元数据则是企业信息门户、客户关系管理、数据仓库、决策支持和B2B等新型应用所不可或缺的内容。 元数据的典型表现为对象的描述,即对数据库、表、列、列属性(类型、格式、约束等)以及主键/外部键关联等等的描述。特别是现行应用的异构性与分布性越来越普遍的情况下,统一的元数据就愈发重要了。“信息孤岛”曾经是很多企业对其应用现状的一种抱怨和概括,而合理的元数据则会有效地描绘出信息的关联性。 而元数据对于ETL的集中表现为:定义数据源的位置及数据源的属性、确定从源数据到目标数据的对应规则、确定相关的业务逻辑、在数据实际加载前的其他必要的准备工作,等等,它一般贯穿整个数据仓库项目,而ETL的所有过程必须最大化地参照元数据,这样才能快速实现ETL。 ETL体系结构 下图为ETL体系结构,它体现了主流ETL产品框架的主要组成部分。ETL是指从源系统中提取数据,转换数据为一个标准的格式,并加载数据到目标数据存储区,通常是数据仓库。
ETL体系结构图 Design manager 提供一个图形化的映射环境,让开发者定义从源到目标的映射关系、转换、处理流程。设计过程的各对象的逻辑定义存储在一个元数据资料库中。 Meta data management 提供一个关于ETL设计和运行处理等相关定义、管理信息的元数据资料库。ETL引擎在运行时和其它应用都可参考此资料库中的元数据。 Extract 通过接口提取源数据,例如?ODBC、专用数据库接口和平面文件提取器,并参照元数据来决定数据的提取及其提取方式。 Transform 开发者将提取的数据,按照业务需要转换为目标数据结构,并实现汇总。 Load 加载经转换和汇总的数据到目标数据仓库中,可实现SQL或批量加载。 Transport services 利用网络协议或文件协议,在源和目标系统之间移动数据,利用内存在ETL处理的各组件中移动数据。 Administration and operation 可让管理员基于事件和时间进行调度、运行、监测ETL作业、管理错误信息、从失败中恢复和调节从源系统的输出。
【翻译】(22)样式与主题
see
http://developer.android.com/guide/topics/ui/themes.html
原文见
http://developer.android.com/guide/topics/ui/themes.html
-------------------------------
Styles and Themes
样式与主题
-------------------------------
In this document
本文目录
* Defining Styles 定义样式
* Inheritance 继承
* Style Properties 样式属性
* Applying Styles and Themes to the UI 应用样式和主题到用户界面
* Apply a style to a View 应用样式到一个View
* Apply a theme to an Activity or application 应用一个主题到一个Activity或应用程序
* Select a theme based on platform version 基于平台版本选择一个主题
* Using Platform Styles and Themes 使用平台样式和主题
See also
另见
Style and Theme Resources 样式与主题资源
R.style for Android styles and themes 用于Android样式和主题的R.style
R.attr for all style attributes 用于所有样式属性的R.attr
-------------------------------
A style is a collection of properties that specify the look and format for a View or window. A style can specify properties such as height, padding, font color, font size, background color, and much more. A style is defined in an XML resource that is separate from the XML that specifies the layout.
样式是一个属性集合,它指定一个View或窗口的外观和格式。一个样式可以指定属性诸如高度,内边距,字体颜色,字体大小,背景颜色,以及更多。一个样式被定义在一个XML资源内,它与指定布局的XML分离。
Styles in Android share a similar philosophy to cascading stylesheets in web design—they allow you to separate the design from the content.
在Android中样式共享一个类似于网页开发中层叠样式表的哲学——它们允许你从内容中分离设计。
For example, by using a style, you can take this layout XML:
例如,通过使用一个样式,你可以把这个布局XML:
-------------------------------
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textColor="#00FF00"
android:typeface="monospace"
android:text="@string/hello" />
-------------------------------
And turn it into this:
把它转成这样:
-------------------------------
<TextView
android:text="@string/hello" />
-------------------------------
All of the attributes related to style have been removed from the layout XML and put into a style definition called CodeFont, which is then applied with the style attribute. You'll see the definition for this style in the following section.
所有与样式相关的属性被移除出布局XML,并且放进一个称为CodeFont的样式定义,然后它被用style属性来应用。你将在以下章节中看到这个样式的定义。
A theme is a style applied to an entire Activity or application, rather than an individual View (as in the example above). When a style is applied as a theme, every View in the Activity or application will apply each style property that it supports. For example, you can apply the same CodeFont style as a theme for an Activity and then all text inside that Activity will have green monospace font.
一个主题是一个应用到整个Activity或应用程序的样式,而非一个单独的View(如上面的示例中那样)。当一个样式被应用为一个主题时,Activity或应用程序中任一View将应用它支持的每个风格属性。例如,你可以应用相同的CodeFont样式作为一个Activity的主题,然后在那个Activity内的所有文本将拥有绿色等宽字体。
-------------------------------
Defining Styles
定义样式
To create a set of styles, save an XML file in the res/values/ directory of your project. The name of the XML file is arbitrary, but it must use the .xml extension and be saved in the res/values/ folder.
为了创建一组样式,保存一个XML文件在你的工程的res/values/目录下。XML文件的名称是任意的,但它必须使用.xml扩展名并且保存在res/values/文件夹中。
The root node of the XML file must be <resources>.
XML文件的根节点必须是<resources>。
For each style you want to create, add a <style> element to the file with a name that uniquely identifies the style (this attribute is required). Then add an <item> element for each property of that style, with a name that declares the style property and a value to go with it (this attribute is required). The value for the <item> can be a keyword string, a hex color, a reference to another resource type, or other value depending on the style property. Here's an example file with a single style:
对于你想创建的每个样式,添加一个<style>元素到文件,带有一个唯一标识样式的名称(这个属性是必需的)。然后为那个样式的每个属性添加一个<item>元素,带有一个声明样式属性的名称和伴随它的值(这个属性是必需的)。<item>的值可以是关键词字符串,十六进制颜色,另一个资源类型的引用,或其它依赖于样式属性的值。这里有一个带有单一样式的示例文件:
-------------------------------
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="CodeFont" parent="@android:style/TextAppearance.Medium">
<item name="android:layout_width">fill_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textColor">#00FF00</item>
<item name="android:typeface">monospace</item>
</style>
</resources>
-------------------------------
Each child of the <resources> element is converted into an application resource object at compile-time, which can be referenced by the value in the <style> element's name attribute. This example style can be referenced from an XML layout as @style/CodeFont (as demonstrated in the introduction above).
<resources>元素的每个子节点在编译期被转换为一个应用程序资源对象,它可以被<style>元素的name属性的值引用。这个示例样式可以从一个XML布局中被引用为@style/CodeFont(正如上面的介绍中所演示的那样)。
The parent attribute in the <style> element is optional and specifies the resource ID of another style from which this style should inherit properties. You can then override the inherited style properties if you want to.
<style>元素中的parent属性是可选的并且指定其它样式的资源ID,而这个样式应该从它那里继承属性。然后你可以覆盖继承的样式属性如果你希望的话。
Remember, a style that you want to use as an Activity or application theme is defined in XML exactly the same as a style for a View. A style such as the one defined above can be applied as a style for a single View or as a theme for an entire Activity or application. How to apply a style for a single View or as an application theme is discussed later.
记住,一个你希望使用作为一个Activity或应用程序主题的样式被定义在XML中,与作为一个View的样式完全相同。一个样式诸如上面定义的那个可以被应用为用于单一View的样式或作为用于整个Activity或应用程序的主题。稍后讨论如何应用样式到一个单一View或作为一个应用程序的主题。
Inheritance
继承
The parent attribute in the <style> element lets you specify a style from which your style should inherit properties. You can use this to inherit properties from an existing style and then define only the properties that you want to change or add. You can inherit from styles that you've created yourself or from styles that are built into the platform. (See Using Platform Styles and Themes, below, for information about inheriting from styles defined by the Android platform.) For example, you can inherit the Android platform's default text appearance and then modify it:
<style>元素的parent属性让你指定一个样式,你的样式应该从这个样式中继承属性。你可以使用它从一个现存样式中继承属性,然后只定义你希望改变或添加的属性。你可以从你曾经自己创建的样式或从内建进平台的样式中继承。(参见下面的使用平台样式和主题章节,获取关于从Android平台定义的样式中继承的信息。)例如,你可以继承Android平台的默认文本外观然后修改它:
-------------------------------
<style name="GreenText" parent="@android:style/TextAppearance">
<item name="android:textColor">#00FF00</item>
</style>
-------------------------------
If you want to inherit from styles that you've defined yourself, you do not have to use the parent attribute. Instead, just prefix the name of the style you want to inherit to the name of your new style, separated by a period. For example, to create a new style that inherits the CodeFont style defined above, but make the color red, you can author the new style like this:
如果你希望从你自己定义的的样式中继承,那么你不必使用parent属性。取而代之的是,只要把你希望继承的样式名称作为你的新样式名称的前缀,通过一个句号来分隔。例如,为了创建一个继承上面定义的CodeFont样式的新样式,但把颜色变成红色,你可以像这样创作新的样式:
-------------------------------
<style name="CodeFont.Red">
<item name="android:textColor">#FF0000</item>
</style>
-------------------------------
Notice that there is no parent attribute in the <style> tag, but because the name attribute begins with the CodeFont style name (which is a style that you have created), this style inherits all style properties from that style. This style then overrides the android:textColor property to make the text red. You can reference this new style as @style/CodeFont.Red.
注意在<style>标签中没有parent属性,但因为name属性以CodeFont样式名称开头(它是你曾经创建的一个样式),这个样式从那个属性中继承所有样式属性。然后这个样式覆盖android:textColor属性使文本变红。你可以引用这个新的样式作为@style/CodeFont.Red。
You can continue inheriting like this as many times as you'd like, by chaining names with periods. For example, you can extend CodeFont.Red to be bigger, with:
你可以通过用句号链接名称,像这样继续继承如你喜欢的那样的多次。例如,你可以用这种方法扩展CodeFont.Red以变得更大:
-------------------------------
<style name="CodeFont.Red.Big">
<item name="android:textSize">30sp</item>
</style>
-------------------------------
This inherits from both CodeFont and CodeFont.Red styles, then adds the android:textSize property.
它同时继承CodeFont和CodeFont.Red风格,然后添加android:textSize属性。
-------------------------------
Note: This technique for inheritance by chaining together names only works for styles defined by your own resources. You can't inherit Android built-in styles this way. To reference a built-in style, such as TextAppearance, you must use the parent attribute.
注意:这种通过链接名称在一起来继承的技术只工作于被你自己的资源定义的样式。你不能用这种方式继承Android的内建样式。为了引用一个内建样式,诸如TextAppearance,你必须使用parent属性。
-------------------------------
Style Properties
样式属性
Now that you understand how a style is defined, you need to learn what kind of style properties—defined by the <item> element—are available. You're probably familiar with some already, such as layout_width and textColor. Of course, there are many more style properties you can use.
现在你理解样式是如何被定义的,你需要知道有什么类型的样式属性——用<itme>元素定义——是可用的。你很可能已经熟悉一些,诸如layout_width和textColor。当然,有其它许多你可以使用的样式属性。
The best place to find properties that apply to a specific View is the corresponding class reference, which lists all of the supported XML attributes. For example, all of the attributes listed in the table of TextView XML attributes can be used in a style definition for a TextView element (or one of its subclasses). One of the attributes listed in the reference is android:inputType, so where you might normally place the android:inputType attribute in an <EditText> element, like this:
找寻被应用到一个特定View的属性的最佳地方是相应的类参考文档,它列举所有支持的XML属性。例如,在TextView XML属性表格中列举的所有属性可以用于TextView元素的样式定义中(或它的其中一个子类)。其中有一个列举在参考中的属性叫android:inputType,所以在你可能通常放置android:inputType属性在一个<EditText>元素内的地方,像这样:
-------------------------------
<EditText
android:inputType="number"
... />
-------------------------------
You can instead create a style for the EditText element that includes this property:
取而代之,你可以为包含这个属性的EditText元素创建一个样式。
-------------------------------
<style name="Numbers">
<item name="android:inputType">number</item>
...
</style>
-------------------------------
So your XML for the layout can now implement this style:
这样你的布局XML现在可以实现这个样式:
-------------------------------
<EditText
... />
-------------------------------
This simple example may look like more work, but when you add more style properties and factor-in the ability to re-use the style in various places, the pay-off can be huge.
这个简单示例可能看起来比较好,但当你添加更多更多样式属性并提取功能因子以在不同的地方重用样式时,开销可能是巨大的。
For a reference of all available style properties, see the R.attr reference. Keep in mind that all View objects don't accept all the same style attributes, so you should normally refer to the specific View class for supported style properties. However, if you apply a style to a View that does not support all of the style properties, the View will apply only those properties that are supported and simply ignore the others.
想获取所有可用样式属性的参考文档,请参见R.attr参考文档。请牢记所有View对象不接受所有相同的样式属性,所以你通常应该对支持的样式属性引用特定的View类。然而,如果你应用一个样式到一个不支持所有样式属性的View,该View将只应用那些支持的属性并且简单地忽略掉其它属性。
Some style properties, however, are not supported by any View element and can only be applied as a theme. These style properties apply to the entire window and not to any type of View. For example, style properties for a theme can hide the application title, hide the status bar, or change the window's background. These kind of style properties do not belong to any View object. To discover these theme-only style properties, look at the R.attr reference for attributes that begin with window. For instance, windowNoTitle and windowBackground are style properties that are effective only when the style is applied as a theme to an Activity or application. See the next section for information about applying a style as a theme.
然而,一些样式属性不被任何View元素支持并且只可以被应用为一个主题。这些样式属性应用到整个窗口而不会应用到任何类型的View。例如,一个主题的样式属性可以隐藏应用程序标题,隐藏状态栏,或改变窗口的背景。这些类型的样式属性不属于任何View对象。为了发现这些只限于主题的样式属性,请查看R.attr关于window开头的属性的参考。例如,windowNoTitle和windowBackground是样式属性,它仅当样式被应用为一个Activity或应用程序的主题时才有效。参见下一章节以获取关于把样式应用为主题的信息。
-------------------------------
Note: Don't forget to prefix the property names in each <item> element with the android: namespace. For example: <item name="android:inputType">.
注意:不要忘记用android:名字空间前缀每个<item>元素的属性名称。例如:<item name="android:inputType">
-------------------------------
-------------------------------
Applying Styles and Themes to the UI
应用样式和主题到用户界面
There are two ways to set a style:
有两种方式设置一个样式:
* To an individual View, by adding the style attribute to a View element in the XML for your layout.
* 对于一个单独的View,通过添加style属性到你的布局XML中的一个View元素。
* Or, to an entire Activity or application, by adding the android:theme attribute to the <activity> or <application> element in the Android manifest.
* 或者,对于整个Activity或应用程序,通过在Android清单中添加android:theme属性到<activity>或<application>元素。
When you apply a style to a single View in the layout, the properties defined by the style are applied only to that View. If a style is applied to a ViewGroup, the child View elements will not inherit the style properties—only the element to which you directly apply the style will apply its properties. However, you can apply a style so that it applies to all View elements—by applying the style as a theme.
当你引用一个样式到布局内的单一View时,被样式定义的属性仅应用在那个View上。如果一个样式被应用到一个ViewGroup,那么子View元素将不会继承样式属性——只有你直接把样式应用到的元素才会应用它的属性。然而,你可以应用一个样式,使它应用到所有View元素——通过应用一个样式作为一个主题。
To apply a style definition as a theme, you must apply the style to an Activity or application in the Android manifest. When you do so, every View within the Activity or application will apply each property that it supports. For example, if you apply the CodeFont style from the previous examples to an Activity, then all View elements that support the text style properties will apply them. Any View that does not support the properties will ignore them. If a View supports only some of the properties, then it will apply only those properties.
为了把一个样式定义应用为一个主题,你必须在Android清单中把样式应用到一个Activity或应用程序。当你这样做时,Activity或应用程序内的每个View将应用它支持的每个属性。例如,如果你应用来自前面示例中的CodeFont样式到一个Activity,那么所有支持text样式属性的View元素将应用它们。任何不支持该属性的View将忽略它们。如果一个View只支持其中一些属性,那么它将只应用那些属性。
Apply a style to a View
应用一个样式到一个View
Here's how to set a style for a View in the XML layout:
这里是如何为XML布局内的View设置样式:
-------------------------------
<TextView
android:text="@string/hello" />
-------------------------------
Now this TextView will be styled as defined by the style named CodeFont. (See the sample above, in Defining Styles.)
现在这个TextView将被样式化为称为CodeFont的样式所定义的那样。(见上面的示例,在定义样式章节中。)
-------------------------------
Note: The style attribute does not use the android: namespace prefix.
注意:style属性不使用android:名字空间前缀。
-------------------------------
Apply a theme to an Activity or application
应用一个主题到一个Activity或应用程序
To set a theme for all the activities of your application, open the AndroidManifest.xml file and edit the <application> tag to include the android:theme attribute with the style name. For example:
为了为你的应用程序的所有活动设置一个样式,打开AndroidManifest.xml文件并编辑<application>标签以包含带有样式名称的android:theme属性。例如:
-------------------------------
<application android:theme="@style/CustomTheme">
-------------------------------
If you want a theme applied to just one Activity in your application, then add the android:theme attribute to the <activity> tag instead.
如果你希望一个主题在你的应用程序中应用到仅一个Activity上,那么改为添加android:theme属性到<activity>标签上。
Just as Android provides other built-in resources, there are many pre-defined themes that you can use, to avoid writing them yourself. For example, you can use the Dialog theme and make your Activity appear like a dialog box:
正如Android提供其他内建资源,有许多你可以使用的预定义主题,以避免自己书写它们。例如,你可以使用Dialog主题让你的Activity显得像一个对话框:
-------------------------------
<activity android:theme="@android:style/Theme.Dialog">
-------------------------------
Or if you want the background to be transparent, use the Translucent theme:
或者如果你希望背景是透明的,那么使用Translucent(注:半透明)主题:
-------------------------------
<activity android:theme="@android:style/Theme.Translucent">
-------------------------------
If you like a theme, but want to tweak it, just add the theme as the parent of your custom theme. For example, you can modify the traditional light theme to use your own color like this:
如果你喜欢一个主题,但希望调整它,那么只要添加该主题作为你自定义主题的父主题。例如,你可以修改传统的浅色主题以使用你自己的颜色,像这样:
-------------------------------
<color name="custom_theme_color">#b0b0ff</color>
<style name="CustomTheme" parent="android:Theme.Light">
<item name="android:windowBackground">@color/custom_theme_color</item>
<item name="android:colorBackground">@color/custom_theme_color</item>
</style>
-------------------------------
(Note that the color needs to supplied as a separate resource here because the android:windowBackground attribute only supports a reference to another resource; unlike android:colorBackground, it can not be given a color literal.)
(注意这里的颜色需要提供以作为一个分离的资源,因为android:windowBackground属性只支持指向另一个资源的引用;不像android:colorBackground,它不能赋予一个颜色字面值。)
Now use CustomTheme instead of Theme.Light inside the Android Manifest:
注意在Android清单中使用CustomTheme而非Theme.Light:
-------------------------------
<activity android:theme="@style/CustomTheme">
-------------------------------
Select a theme based on platform version
基于平台版本选择一个主题
Newer versions of Android have additional themes available to applications, and you might want to use these while running on those platforms while still being compatible with older versions. You can accomplish this through a custom theme that uses resource selection to switch between different parent themes, based on the platform version.
较新版本的Android拥有对于应用程序可用的附加主题,而你可能希望在运行于这些平台上时使用这些主题但仍然兼容较旧的版本。你可以通过一个使用资源选择以切换不同的父主题的自定义主题来做到这点,基于平台版本。
For example, here is the declaration for a custom theme which is simply the standard platforms default light theme. It would go in an XML file under res/values (typically res/values/styles.xml):
例如,这里是用于自定义主题的声明,它简单地是标准平台的默认浅色主题。它将放进res/values下的一个XML文件(典型地是res/values/styles.xml):
-------------------------------
<style name="LightThemeSelector" parent="android:Theme.Light">
...
</style>
-------------------------------
To have this theme use the newer holographic theme when the application is running on Android 3.0 (API Level 11) or higher, you can place an alternative declaration for the theme in an XML file in res/values-v11, but make the parent theme the holographic theme:
为了让这个主题在运行于Android 3.0(API级别11)或更高时使用较新的全息主题,你可以在res/values-v11内的一个XML文件中放置这种主题的可选声明,但要让父主题是全息主题:
-------------------------------
<style name="LightThemeSelector" parent="android:Theme.Holo.Light">
...
</style>
-------------------------------
Now use this theme like you would any other, and your application will automatically switch to the holographic theme if running on Android 3.0 or higher.
现在像你用其它任意主题那样使用这种主题,并且你的应用程序将自动地切换到全息主题如果它运行在Android 3.0或更高。
A list of the standard attributes that you can use in themes can be found at R.styleable.Theme.
在主题中你可以使用一列能在R.styleable.Theme中找到的标准属性。
For more information about providing alternative resources, such as themes and layouts, based on the platform version or other device configurations, see the Providing Resources document.
想获取关于提供可选资源的更多信息,诸如主题和布局,基于平台版本或其它设备配置,请参见提供资源文档。
-------------------------------
Using Platform Styles and Themes
使用平台样式和主题
The Android platform provides a large collection of styles and themes that you can use in your applications. You can find a reference of all available styles in the R.style class. To use the styles listed here, replace all underscores in the style name with a period. For example, you can apply the Theme_NoTitleBar theme with "@android:style/Theme.NoTitleBar".
Android平台提供一个大的样式和主题集合,你可以在你的应用程序中使用它们。你可以在R.style类中找到所有可用样式的参考文档。为了使用这里列举的样式,请把样式名中所有下环线替换为句号。例如,你可以用"@android:style/Theme.NoTitleBar"应用Theme_NoTitleBar主题。
The R.style reference, however, is not well documented and does not thoroughly describe the styles, so viewing the actual source code for these styles and themes will give you a better understanding of what style properties each one provides. For a better reference to the Android styles and themes, see the following source code:
然而,R.style的参考文档并不被良好地文档化而且没有彻底描述样式,所以查看这些样式和主题的实际源代码将让你更好地理解每个样式提供什么样式属性。想获取对Android样式和主题的较好参考,请参见以下源代码:
* Android Styles (styles.xml)
* Android样式(style.xml)
* Android Themes (themes.xml)
* Android主题(themes.xml)
These files will help you learn through example. For instance, in the Android themes source code, you'll find a declaration for <style name="Theme.Dialog">. In this definition, you'll see all of the properties that are used to style dialogs that are used by the Android framework.
这些文件将帮助你用示例来学习。例如,在Android主题源代码中,你将找到<style name="Theme.Dialog">的声明。在这个声明中,你将看到用于样式化被Android框架所使用的对话框的所有属性。
For more information about the syntax used to create styles in XML, see Available Resource Types: Style and Themes.
想获取关于XML中创建样式所使用的语法的更多信息,请参见可用资源类型:样式和主题。
For a reference of available style attributes that you can use to define a style or theme (e.g., "windowBackground" or "textAppearance"), see R.attr or the respective View class for which you are creating a style.
想获取你可以用于定义样式或主题的可用style属性的参考文档(例如,"windowBackground"或"textAppearance"),请参考R.attr或你创建样式所对应的View类。
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来源许可证描述的条款进行修改)
【翻译】(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
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来源许可证描述的条款进行修改)