Android官方文档阅读之旅——Creating a View Class

Android官方文档阅读之旅——Creating a View Class

原文地址:http://developer.android.com/training/custom-views/create-view.html#subclassview

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:

一个设计良好的自定义View非常类似于一个设计良好的Class。它封装了一个特定的,带有易用UI界面的功能集合,它会高效的利用CPU和内存等等。然而,除了具有一个设计良好的Class的特性之外,一个自定义的View还应该具有以下特点:

  • Conform to Android standards
  • Provide custom styleable attributes that work with Android XML layouts
  • Send accessibility events
  • Be compatible with multiple Android platforms.
  • 符合Android规范
  • 提供兼容Android XML 布局文件的自定义样式属性
  • 可发送辅助功能事件
  • 兼容多种不同版本Android系统

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.

Android 系统框架提供了一系列基本类和XML标签以帮助你创建满足这些需求的View。本教程将讨论如何使用系统框架去创建一个View类的核心功能。

Subclass a View 继承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.

所有定义在Android框架中的View对象都继承了View类。你的自定义View可以直接继承View,或者为了节约时间,也可转而继承一个已经存在的View类,如Button。

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.

为了允许Android Studio能够和你的View交互,你必须至少提供一个包含Context和AttributeSet对象参数的构造器。这个构造器允许布局编辑器创建并编辑一个你的View实例。

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:

为了向你的用户界面中添加一个系统内置的View控件,你会在XML的一个元素中声明它,并通过属性控制它的外表以及行为。设计良好的自定义View也应该可以通过XML进行添加并编辑属性。为了让你的自定义View支持这样的特性,你必须:

  • 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
  • 在一个<declare-styleable>资源节点上为你的View定义一组自定义属性。
  • 在你的XML布局文件中为这些属性赋值
  • 在运行时检索这些属性值
  • 为你的View分配这些检索到的属性值。

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:

为了自定义属性,你需要向你的工程中添加<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的样式实体。按照惯例,一个样式实体的名字就是自定义View的类名。虽然遵守此惯例并非必须,但是很多主流代码编辑器都会根据此命名规范决定代码块是否结束。

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布局文件中使用它们,如同使用系统内置的属性那样。唯一不同之处在于你的这些自定义属性属于一个不同的命名空间。 它们不属于 http://schemas.android.com/apk/res/android namespace,而是属于http://schemas.android.com/apk/res/[你的包名称]。例如,下面就展示了如何使用为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.

为了避免重复这些长命名空间URI,这个样例使用了一个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.

关注一下向布局中添加自定义View的XML标签的名字。它是自定义View类的全名。如果你的View类是一个内部类,你必须利用此View的外部类名以更加明确它。例如,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:

一个XML布局文件中声明一个View时,在XML标签里的所有属性都会从资源文件中被读取出来,并作为一个AttributeSet对象传入到View的构造器中。虽然可以直接从AttributeSet中读取属性值,但是这么做会存在一些风险:

  • Resource references within attribute values are not resolved
  • Styles are not applied
  • 此属性值对应的资源文件并没有被解析
  • 样式没有被应用

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 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:

Android资源编译器为你做了大量工作以让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:

属性是一个控制View形态以及行为的有效手段,但是只有在View被初始化后才能被读取。为了提供动态的行为,你需要向外暴漏每个自定义属性的一对getter和setter方法。下面的代码段就展示了PieChart是如何向外暴漏名为showText的属性的:

“`
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()。这些调用对于确保View行为的可靠性是十分必要的。当改变了任何可能引起View形状的属性时,你就需要作废这个View,从而让系统知道这个View需要重绘。同样的,如果一个属性的改变可能引起View大小或者形状的改变,那么你就需要重新布局了。忘记这些方法的调用可能会引起很多非常隐晦的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.

自定义View应该支持事件监听器以对重要事件进行反应。比如,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.

我们很容易遗忘向外界暴露属性或者事件,尤其是当我们是此自定义控件唯一的用户。在定义View时多花些功夫可以减少未来维护它的成本。这里有个非常好的值得永远遵守的准则——向外暴漏任何可能影响此自定义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:

你的自定义View应该支持多样的用户,其中包含那些具有生理残疾的人群。他们往往无法看到或者使用触摸屏。为了方便这些残疾人士,你应该:

  • 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()发送辅助功能事件
  • 兼容多类型控制器,如 D-pad 或者轴迹球

For more information on creating accessible views, see Making Applications Accessible in the Android Developers Guide.

预知更多关于创建支持辅助功能的View的信息,请参阅安卓开发向导的《Making Applications Accessible(让应用支持辅助功能)》章节。


由于笔者水平有限,内容仅供参考,如有翻译不当之处,欢迎指正

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值