原:
A well-designed custom view is much like any other well-designed class. It encapsulates a specific set of functionality with an easy to use interface, it uses CPU and memory efficiently, and so forth. In addition to being a well-designed class, though, a custom view should:
- Conform to Android standards
- Provide custom styleable attributes that work with Android XML layouts
- Send accessibility events
- Be compatible with multiple Android platforms.
译:
一个设计优秀的视图和任何其他设计优秀的类一样。它包含了一个具体的函数集,这些函数接口简单,使用方便,它有效地利用CPU和内存资源等。除了作为一个设计优秀的类之外,自定义的视图还应该具备:
- 符合安卓标准
- 在安卓的xml布局文件中创建自定义的风格属性
- 发送无障碍事件
- 能够兼容多种安卓设备
原:
The Android framework provides a set of base classes and XML tags to help you create a view that meets all of these requirements. This lesson discusses how to use the Android framework to create the core functionality of a view class.
译:
安卓框架提供了一套基本的类集合和xml标签来帮助你创建符合所有需求的视图。这一节讨论如何使用安卓框架来创建视图类的核心功能。
Subclass a View 创建视图的子类
原:
All of the view classes defined in the Android framework extend View. Your custom view can also extend View directly, or you can save time by extending one of the existing view subclasses, such as Button.
译文:
安卓应用程序框架中定义的所有的其他的视图类都扩展自View视图类。你自定义的视图也可以直接扩展自View类,或者你可以节省些时间,直接扩展那些已经存在的视图类的子类,比如说按钮。
原:
To allow Android Studio to interact with your view, at a minimum you must provide a constructor that takes a Context and an AttributeSet object as parameters. This constructor allows the layout editor to create and edit an instance of your view.
class PieChart extends View {
public PieChart(Context context, AttributeSet attrs) {
super(context, attrs);
}
}
译文:
为了让Android Studio能够和你的视图进行交互,你至少必须要提供一个构造方法,并且将Context上下文和属性集实例作为参数传入该构造方法。这个构造方法能够让布局编辑器创建并编辑你自定义视图的实例。
class PieChart extends View {
public PieChart(Context context, AttributeSet attrs) {
super(context, attrs);
}
}
Define Custom Attributes 定义自定义的属性
原:
To add a built-in View to your user interface, you specify it in an XML element and control its appearance and behavior with element attributes. Well-written custom views can also be added and styled via XML. To enable this behavior in your custom view, you must:
- Define custom attributes for your view in a < declare-styleable > resource element
- Specify values for the attributes in your XML layout
- Retrieve attribute values at runtime
- Apply the retrieved attribute values to your view
译文:
为了在你的界面中增加一个内置的视图,你应该在XML元素中指定并且设置元素的属性来控制它的外观和行为。设计优秀的自定义视图应能通过XML布局文件进行添加和风格化。为了能够让你自定义的视图拥有这样的行为,你必须:
- 在< declare-styleable >元素中为你的视图定义自定义的属性
- 在你的XML布局文件中为属性指定一定的值
- 在程序运行期间获取属性的值
- 在你的视图中应用获取的属性值
原文:
This section discusses how to define custom attributes and specify their values. The next section deals with retrieving and applying the values at runtime.
To define custom attributes, add < declare-styleable > resources to your project. It’s customary to put these resources into a res/values/attrs.xml file. Here’s an example of an attrs.xml file:
<resources>
<declare-styleable name="PieChart">
<attr name="showText" format="boolean" />
<attr name="labelPosition" format="enum">
<enum name="left" value="0"/>
<enum name="right" value="1"/>
</attr>
</declare-styleable>
</resources>
译文:
这一节讨论如何定义自定义的属性并且指定它们的值。下一节处理程序运行期间获取并应用属性值。
为了定义自定义的属性,要向你的工程中添加< declare-styleable >资源。一般将这些资源放进一个 /res/values/attrs.xml文件中。下面是一个 attrs.xml文件的例子:
<resources>
<declare-styleable name="PieChart">
<attr name="showText" format="boolean" />
<attr name="labelPosition" format="enum">
<enum name="left" value="0"/>
<enum name="right" value="1"/>
</attr>
</declare-styleable>
</resources>
原文:
This code declares two custom attributes, showText and labelPosition, that belong to a styleable entity named PieChart. The name of the styleable entity is, by convention, the same name as the name of the class that defines the custom view. Although it’s not strictly necessary to follow this convention, many popular code editors depend on this naming convention to provide statement completion.
译文:
这块代码声明了两个自定义的属性,showText和labelPosition,隶属于一个叫PieChart的styleable实例。这个styleavle实例的名称习惯上是和你自定义的视图类的名称相同。虽然没有严格要求遵循这个惯例,但许多主流的代码编辑器依靠这种命名惯例来提供语句自动补全功能。
原:
Once you define the custom attributes, you can use them in layout XML files just like built-in attributes. The only difference is that your custom attributes belong to a different namespace. Instead of belonging to the http://schemas.android.com/apk/res/android namespace, they belong to http://schemas.android.com/apk/res/[your package name]. For example, here’s how to use the attributes defined for PieChart:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res/com.example.customviews">
<com.example.customviews.charting.PieChart
custom:showText="true"
custom:labelPosition="left" />
</LinearLayout>
译文:
一旦你定义了自定义的属性,你将能够在XML布局文件中使用它们,就像使用内置的属性一样。唯一的不同是你自定义的属性属于不同的命名空间。它们属于http://schemas.android.com/apk/res/[your package name]而不再属于http://schemas.android.com/apk/res/android 命名空间。比如,这是如何使用定义在PieChart中的属性的例子:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res/com.example.customviews">
<com.example.customviews.charting.PieChart
custom:showText="true"
custom:labelPosition="left" />
</LinearLayout>
原:
In order to avoid having to repeat the long namespace URI, the sample uses an xmlns directive. This directive assigns the alias custom to the namespace http://schemas.android.com/apk/res/com.example.customviews. You can choose any alias you want for your namespace.
译:
为了避免重复使用冗长的命名空间(写起来多麻烦,看着也不舒服),这个例子使用了xmlns指令。这个指令为
http://schemas.android.com/apk/res/com.example.customviews 这个长长的命名空间设置了一个别名。你可以为你的命名空间选择任何别名。
原:
Notice the name of the XML tag that adds the custom view to the layout. It is the fully qualified name of the custom view class. If your view class is an inner class, you must further qualify it with the name of the view’s outer class. further. For instance, the PieChart class has an inner class called PieView. To use the custom attributes from this class, you would use the tag com.example.customviews.charting.PieChart
PieView.译:注意向布局中加入自定义视图中的XML标签的名称,它是自定义视图类的完全限定名称。如果你的视图类是一个内部类,你必须要为其指定该视图外部类的名称。例如,这个PieChart类有一个内部类叫PieView,为了使用这个类中自定义的属性,你需要使用com.example.customviews.charting.PieChart
PieView标签。
Apply Custom Attributes 应用自定义的属性
原:
When a view is created from an XML layout, all of the attributes in the XML tag are read from the resource bundle and passed into the view’s constructor as an AttributeSet. Although it’s possible to read values from the AttributeSet directly, doing so has some disadvantages:
- Resource references within attribute values are not resolved
- Styles are not applied
译:
当从XML布局文件中创建出一个视图之后,所有在XML标签中的属性将被读入到resource bundle中并且被作为AttributeSet参数传递到这个视图的构造方法中。虽然可以直接从AttributeSet中读取数据,但这么做有如下缺点:
- 属性值中对资源的引用将无法解决
- 风格不会被应用
原:
Instead, pass the AttributeSet to obtainStyledAttributes(). This method passes back a TypedArray array of values that have already been dereferenced and styled.
译:
应该将AttributeSet参数传递给obtainStyledAttributes(),这个方法返回一个TypedArray数组。?
原:
The Android resource compiler does a lot of work for you to make calling obtainStyledAttributes() easier. For each < declare-styleable > resource in the res directory, the generated R.java defines both an array of attribute ids and a set of constants that define the index for each attribute in the array. You use the predefined constants to read the attributes from the TypedArray. Here’s how the PieChart class reads its attributes:
译:
为了你能够更加容易的调用obtainStyledAttributes()方法,安卓的资源编译器做了很多工作。res目录中的每个< declare-styleable >资源,自动生成的R.java文件定义了属性id数组和常量,这些常量定义了数组中每个属性的索引值。你可以使用预定义的常量来读取TypedArray中的属性。下面是PieChart怎样读取它属性值的例子:
public PieChart(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.getTheme().obtainStyledAttributes(
attrs,
R.styleable.PieChart,
0, 0);
try {
mShowText = a.getBoolean(R.styleable.PieChart_showText, false);
mTextPos = a.getInteger(R.styleable.PieChart_labelPosition, 0);
} finally {
a.recycle();
}
}
原:
Note that TypedArray objects are a shared resource and must be recycled after use.
译文:
注意TypedArray对象是一个共享的资源,使用之后必须被循环利用。
Add Properties and Events 添加特性和事件
原:
Attributes are a powerful way of controlling the behavior and appearance of views, but they can only be read when the view is initialized. To provide dynamic behavior, expose a property getter and setter pair for each custom attribute. The following snippet shows how PieChart exposes a property called showText:
译:
属性是控制视图的动作和外观的强有力的方法,但是它们只能在视图被初始化的时候进行读取。为了提供动态的行为,可以对外为每个自定义的属性提供getter和setter方法对。下面的代码片段展示了PieChart如何对外提供了一个叫做shouText的属性:
public boolean isShowText() {
return mShowText;
}
public void setShowText(boolean showText) {
mShowText = showText;
invalidate();
requestLayout();
}
原:
Notice that setShowText calls invalidate() and requestLayout(). These calls are crucial to ensure that the view behaves reliably. You have to invalidate the view after any change to its properties that might change its appearance, so that the system knows that it needs to be redrawn. Likewise, you need to request a new layout if a property changes that might affect the size or shape of the view. Forgetting these method calls can cause hard-to-find bugs.
译:
注意setShowText方法调用了invalidate()和requestLayout()方法。这些调用对于保证视图能够可靠的动作是至关重要的。你必须在任何可能改变视图外观的属性被修改之后使视图无效,这样系统才知道应该重新绘制视图。同样,如果一个可能影响视图尺寸或者形状的属性被修改之后,你也需要请求一个新的布局。忽略这些方法调用会导致难以寻找到的bug。
原:
Custom views should also support event listeners to communicate important events. For instance, PieChart exposes a custom event called OnCurrentItemChanged to notify listeners that the user has rotated the pie chart to focus on a new pie slice.
译:
自定义的视图应该同样支持事件监听器以便和重要的事件进行通信。例如,PieChart对外提供了一个自定义的事件叫做OnCurrentItemChanged来通知监听器用户已经旋转了饼状图用于切换到一个新的饼片。
原:
It’s easy to forget to expose properties and events, especially when you’re the only user of the custom view. Taking some time to carefully define your view’s interface reduces future maintenance costs. A good rule to follow is to always expose any property that affects the visible appearance or behavior of your custom view.
译:
很容易会忽略对外提供属性和事件,特别是当你是这个自定义视图唯一的使用者的时候。花点时间认真定义你的视图的接口来减少将来的维护成本。一个好的可以遵循的做法是始终对外提供任何影响你自定义视图的外观或者动作的属性。
Design For Accessibility 无障碍设计
原:
Your custom view should support the widest range of users. This includes users with disabilities that prevent them from seeing or using a touchscreen. To support users with disabilities, you should:
- Label your input fields using the android:contentDescription attribute
- Send accessibility events by calling sendAccessibilityEvent() when appropriate.
- Support alternate controllers, such as D-pad and trackball
译:
你的自定义的视图应该能够最大限度地支持更多的用户。包括那些不能看到或者使用触摸屏的用户。为了支持这些受限制的用户,你应该:
- 使用android:contentDescription 属性来为你的输入框添加标签
- 在适当的时候调用sendAccessibilityEvent()方法发送无障碍事件
- 支持可选择的控制器,例如方向键和轨迹球。
原:
For more information on creating accessible views, see Making Applications Accessible in the Android Developers Guide.
译:
获取更多创建可访问的视图,请参见安卓开发者文档的Making Applications Accessible相关章节。