Creating a View Class//建立视图类
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很像其它的那些设计好的类。它以一个易用的界面封装了一组特定的功能,它高效地使用cpu和内存等等.要成为一个设计良好的类,初次之外,一个自定义的类还应该:
1)Conform to Android standards//符合安卓标准
2)Provide custom styleable attributes that work with Android XML layouts//通过使用Android XML布局提供定制styleable属性
3)Send accessibility events//发送可用的事件
4)Be compatible with multiple Android platforms.//兼容不同的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.
//安卓框架提供了一系列的基础类和xml标签帮助你建立满足这些要求的一个view。这一课讨论如何使用安卓框架在一个view类里去建立更多的函数。
Subclass a View//子类视图
All of the view classes defined in the Android framework extend View
. Your custom view can also extendView
directly, or you can save time by extending one of the existing view subclasses, such asButton
.
//在安卓框架里定义的所有的视图类都继承自view.自己的自定义类也要直接继承View类,或者你也可以通过继承一个已经存在的子类,例如button,以节省时间。
To allow the Android Developer Tools to interact with your view, at a minimum you must provide a constructor that takes aContext
and anAttributeSet
object as parameters. This constructor allows the layout editor to create and edit an instance of your view.
//为了让安卓框架与你的view互动,最低限度你需要提供一个构造函数,这个构造函数带一个Context对象和一个AttributeSet对象最为参数。这个构造函数允许布局编辑器去建立和编辑你自己的view实例。
示例代码:
class PieChartextendsView{
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元素指定它,并且通过元素的属性控制它的出现和行为。编写良好的自定义视图可以通过xml添加和作为样式。要在你的定制视图里面表现出这些行为,你必须:
1)Define custom attributes for your view in a <declare-styleable>
resource element.
//在resource元素里面通过<declare-styleable>为你的视图定义自定义的属性。
2)Specify values for the attributes in your XML layout.
//在你的xml布局里面为属性指定值。
3)Retrieve attribute values at runtime.
//在运行时检索属性值
4)Apply the retrieved attribute values to your 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 anattrs.xml
file:
//在你工程里面的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 namedPieChart
. 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和lablPosition,它们属于一个叫作PieChart的格式实体。按照惯例,这个格式实体的名字和在自定义视图类中定义的名字是一样的.尽管没有必要一定要遵守这个惯例,很多流行的代码编辑器都依赖于这个名字惯例去完成语句的声明。
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 thehttp://schemas.android.com/apk/res/android
namespace, they belong tohttp://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/[your package name]".例如,这里是如何使用为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.
//为了避免重复使用一个长的命名空间,这个例子使用了xml指令。这个指令为命名空间"http://schemas.android.com/apk/res/com.example.customviews"分配了别名"custom".你可以为你的命名空间选择任何你想要的别名。
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//应用自定义属性
AttributeSet
. Although it's possible to read values from the
AttributeSet
directly, doing so has some disadvantages:
AttributeSet
to obtainStyledAttributes()
. This method passes back a TypedArray
array of values that have already been dereferenced and styled.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: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.
Add Properties and Events//增加属性和事件
PieChart
exposes a property called
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.
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.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//设计的可访问性
android:contentDescription
attribute
sendAccessibilityEvent()
when appropriate.