创建Android View类

来源:互联网 发布:血源诅咒白狼捏脸数据 编辑:程序博客网 时间:2024/06/05 03:00

译自:http://developer.android.com/training/custom-views/create-view.html,有删减。


  1、创建View类

  完美的自定义可以封装原UI的方便功能,可以带来CPU和内存上的使用效率,等等。尽管如此,自定义view类还应该:

  · 与Android标准一致

  · 提供能运用于Android XML布局的自定义属性

  · 发送可访问性事件

  · 与多种Android平台兼容

  Android框架提供了一系列基础类和XML标记,来帮助我们创建适用各种需求的view。

  2、View子类

  所有视图类都继承于View类。自定义类当然也可以从View类直接继承,或者图省事从子类(如Button)继承。

  为了让Android开发工具可以与我们自己定义的view类交互,我们必须创建包含有Context和AttributeSet类型的对象作为参数的构造函数。

  class PieChart extends View {
      public PieChart(Context context, AttributeSet attrs) {
          super(context, attrs);
      }

  }

  3、自定义属性

  对于内置View类而言,我们通过指定对应XML元素中的属性便可以控制它的显示样式和行为举止。完美的自定义view也可以如此,但必须通过以下步骤来实现:

  · 通过<declare-styleable>资源定义自定义属性。
  · 在XMl布局为属性赋值。
  · 运行时取得属性值
  · 运用该值控制自定义view的显示
  <declare-styleable>资源通常可放在res/values/attrs.xm中,如:
<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>

  以上代码为PieChart类定义了两个属性,showText、labelPosition。通常name=""中的内容应该与自定义View中的声明一致,尽管没有明确的要求XML和类对name的声明一致,但流行的代码编辑器在语句校对中还是很依赖于这种一致性的。

  在使用自定义属性时,还需要注意的是,它们与内置属性的命名空间不一致,默认的命名空间为:http://schemas.android.com/apk/res/android,自定义属性的命名空间为http://schemas.android.com/apk/res/[你的包名]:

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

  为了避免重复长长的命名空间URI,示例中采用了xmlns指示符,还自定义了一个命名空间别名:http://schemas.android.com/apk/res/com.example.customviews。如你所好,你可以选择自己想要的任意命名空间别名。

  请注意添加到布局中的自定义视图标记哦,这可是自定义视图类的全称。如果是内置类,还必须用外置类的名称限定它。比如PieChart类包含一个内置类,被称为PieView。要使用这个类的自定义属性,应该使用com.example.customviews.charting.PieChart$PieView标记。



  应用自定义内置属性
  当视图从XML布局创建之时,所有从资源包中读取并传递到视图类构造函数中的内置属性将构成一个AttributeSet中。但尽管可以从AttributeSet中直接读取属性值,但这样做有一些缺点:

  ·属性值内的资源引用不会被解析。
  ·Styles不会被应用。

  与之相反的是,将AttributeSet 传递给obtainStyledAttributes(),将会返回已被去引用和风格化的TypedArray值。

  Android资源编译器的大量工作使得调用obtainStyledAttributes() 更为方便。对于res目录下每一个<declare-styleable>资源来说,所产生的R.java既定义了属性数组,又包含了数组中每个属性的索引常量集合。我们在从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();
   }

}

  注意:TypedArray对象是一个共享资源,用后必须回收。


  增加外置属性和事件

  内置属性对于描述视图的行为和外观而言足够了,但内置属性仅可以在视图初始化时读取。如果要实现动态的行为,可以通过在外置属性的getter和setter方法中访问对应内置属性来实现。 比如,PieChart实现了一个外置属性showText。


public boolean isShowText() {
   return mShowText;
}


public void setShowText(boolean showText) {
   mShowText = showText;
   invalidate();
   requestLayout();

}

 注意:setShowText调用了invalidate() 和requestLayout()函数。这些调用对于保持视图行为的可靠性是至关重要的。任何对外置属性的改变都可能导致显示效果的改变,因此必须在属性改变之后废除旧有视图,这样系统就会晓得:哦,视图需要重画了。同样,如果属性的改变可能导致视图大小或形状的变化,那么就需要申请一个新布局。如果忘记了调用invalidate() 和requestLayout()函数的话,非你所愿的Bug是很难排除的哦。


  自定义视图也应该支持事件侦听器,以便于对重要事件作出相应。比如,PieChart创造了一个OnCurrentItemChanged自定义事件,以便于通知事件侦听器用户已经旋转饼图,要关注新扇形。


  我们很容易就会忘记将属性和事件暴露出来,特别当你只是一个自定义视图的使用者时。差之毫厘,谬以千里。最好的办法是养成始终将能影响自定义视图外观和行为的属性暴露给别人的好习惯。


  4、为可访问性而设计

  自定义视图应该能支持越多的用户越好。当然要包括对残疾朋友在“看”或“用”触摸屏时的考虑。因此,我们需要:

  用android:contentDescription属性说明你的输入框。

  适时调用sendAccessibilityEvent() 以传递辅助事件。

  要支持改变控制器,比如D-pad和轨迹球。

  For more information on creating accessible views, see Making Applications Accessible in the Android Developers Guide.
0 0
原创粉丝点击