现在的位置: 首页 > 综合 > 正文

android构建自定义的视图组件

2013年09月18日 ⁄ 综合 ⁄ 共 3711字 ⁄ 字号 评论关闭
文章目录

转自 http://marshal.easymorse.com/archives/2062

 

android提供了精巧和有力的组件化模型构建用户的UI部分。主要是基于布局类:View和ViewGroup。在此基础上,android平
台提供了大量的预制的View和ViewGroup子类,即布局(layout)和窗口小部件(widget)。可以用它们构建自己的UI。

如果没有符合你需求的预制窗口小部件,你可以创建自己的视图子类。如果只是对已存在的窗口小部件或者布局做小的调整,只需继承该类,覆盖相关的方
法。

创建你自己的View子类可以更精确控制视图元素的外观和功能。

  • 可创建完整的自定义渲染视图类型,比如创建一个2d的控制条;
  • 可将一组视图组件合成为一个新的单一组件,比如双选的列表,选择省和市;
  • 覆盖EditText组件,比如notepad
    tutorial

    中的示例;

  • 捕捉其他事件比如按键事件,并执行自定义的处理方式,比如在游戏中。

 

基本方法

总的来说,创建自定义的视图组件步骤是:

  1. 创建自己的类,继承已经存在的View类或者子类;
  2. 覆盖超类的一些方法。这些超类的方法一般以“on”开头,比如onDraw()方法等等;
  3. 使用新创建的扩展类。一旦完成,你的新扩展类就可以用于所有View使用的地方。

注意:

扩展类可以定义为内部类,在你创建的Activity类之中。这很有用,因为这
样可以控制外界的访问,但是这不是必须的,因为你可能需要一个public的自定义View类供更广泛的使用。

完全自定义组件

完全自定义的组件可以创建图形组件显示在你需要的任何地方。

步骤如下:

  1. 可以继承的最通用的视图类是View,可以继承它创建自定义的组件超类;
  2. 可以提供构造方法,并通过xml文件获取属性值和参数;
  3. 创建自己的事件监听器,属性访问器和编辑器等等;
  4. 一般情况下会覆盖onMeasure()方法和onDraw()方法,这会让组件显示一些东西。如果都用默认的行为,onDraw()方法不做任
    何事情,onMeasure()方法设置一个100×100的区域;
  5. 根据需求覆盖其他on…方法。

扩展onDraw()和onMeasure()方法

onDraw()方法提供给你一个Canvas对象,在它之上可以实现任何你想要的东西,通过2d图形api。比如其他标准的后者自定义的组件,风
格化的文字后者其他。

注意:这里
不提供3d图形api的支持。如果你需要3d图形支持,必须继承SurfaceView而不是View,并且通过单独的线程画图。可以通过
GLSurfaceViewActivity实例查看详细信息。

onMeasure()方法有些麻烦。该方法是在容器和自定义组件之间渲染的重要部分。该方法覆盖,要高效率的和精确的报告被包含区域的测量值。

总的来看,实现onMeasure()方法类似如下步骤:

  1. 调用已经覆盖的onMeasure()方法,传递长和宽规范参数;
  2. 自定义组件在onMeasure()方法中计算需要渲染的组件的长和宽,应该在规范参数的范围内;
  3. 一旦长和宽计算出来,必须调用setMeasuredDimension(int width, int
    height)方法,这步失败会导致异常的抛出。

扩展onAttachedToWindow()和onDetachedFromWindow()方法

分别在当视图从一个窗口拆分开时被调用。当包含视图的窗口的可见性发生改变时被调用。

 

类别Category 方法Methods 描述Description

构造器 有一种构造器形式是在从代码里创建视图时被调用,另一种是从一个布局文件中扩充视图时被调
用。第二种形式应该解析并运用任何定义在布局文件中的属性。
创建 onFinishInflate()
一个视图及其所有子项已经在XML中扩充好时被调用。
布局 onMeasure(int,
int)
用来决定这个视图及其所有子项的尺寸要求。
布局 onLayout(boolean,
int, int, int, int)
当这个视图应该为它所有的子项分配一个尺寸和位置的时候调用。

onSizeChanged(int, int, int, int) 当这个视图的尺寸被改变时
被调用。
绘画 onDraw(Canvas) 当视图
需要绘制其内容时被调用。
事件处理 onKeyDown(int,
KeyEvent)
当一个按键事件发生时被调用。
事件处理 onKeyUp(int,
KeyEvent)
当一个按键释放事件发生时调用。
事件处理 onTrackballEvent(MotionEvent)
一个跟踪球动作事件发生时被调用。
事件处理 onTouchEvent(MotionEvent)
一个触摸屏动作事件发生时被调用。
Focus onFocusChanged(boolean,
int, Rect)
当视图获取或丢失焦点时被调用。
Focus onWindowFocusChanged(boolean)
包含视图的窗口获取或丢失焦点时被调用。
Attaching onAttachedToWindow()
视图被附着到一个窗口时被调用。
Attaching onDetachedFromWindow()
视图从一个窗口拆分开时被调用。
Attaching onWindowVisibilityChanged(int)
包含视图的窗口的可见性发生改变时被调用。

一个自定义视图的示例

自定义视图的示例,见:LabelView

该示例演示了一些自定义组件的不同方面:

  • 继承View类,用于完全自定义组件;
  • 参数化的构造方法,提供更多的参数,定义在xml文件中;
  • 标准的公开方法,用于设置标签,比如setText()方法等;
  • 覆盖onMeasure方法确定渲染的组件尺寸;
  • 覆盖onDraw方法,在提供的canvas中画标签。

可以找到对示例的一些使用,在custom_view_1.xml文件中。

该示例运行效果:

image

android示例是混在一起的,比较乱,我这里改写了一下,只有相关示例的代码和配置。看起来比较简单:

http://easymorse.googlecode.com/svn/tags/android.customer.view.demo_1.0

 

合成控件

合成控件,即不是完全自定义一个新的视图组件,而是,将现有的原子级控制器(控件)或者视图组件组合在一起,处理共同的业务逻辑。比如,一个
combo box可以被看做,一个单行的EditText和一个相邻的按钮,带一个弹出列表。

在android中还有很多其他的示例,比如Spinner,AutoComleteTextView。

创建合成控件的步骤:

  1. 通常的起始步骤是,创建某种类型的Layout,即创建一个类继承一个Layout。比如上述的combo
    box,可能会使用到基于垂直布局的LinearLayout。其他布局也可以嵌套在其中,因此合成组件可以任意复杂结构。和activity类似,你可
    以用基于xml的声明方式创建容器组件,也可以嵌入到程序代码中;
  2. 在新类的构造方法中,得到超类所需的参数,并传递给超类的构造方法。另外,也可设置其他在这个新组件当中的视图组件,比如创建一个
    EditText和PopupList。注意,你也可以引入自己的参数和属性到xml文件中,这样会被取出并用于你的构造方法;
  3. 还可以创建事件监听器,用于容器中的视图组件,比如一个监听器方法,用于处理列表点击的监听器,更新EditText的文本内容;
  4. 创建自己的属性访问器和编辑器,比如,EditText的值可以在组件中初始设置,并能在需要的时候获取它的值;
  5. 在继承Layout类时,不需要覆盖onDraw()和onMeasure()方法,因为它们可能已经符合你的要求,当然,也可以覆盖它们实现自
    己特定的需求;
  6. 可能需要覆盖其他on…方法,比如onKeyDown()方法。

总之,使用Layout作为基础合成自定义的控件,有一些优点:

  • 可以通过xml文件的方式声明指定的布局,和activity类似,或者可以通过编程的方式嵌入到你的代码中;
  • onDraw()方法和onMeasure()等一般可适合需求,因此不必一定要覆盖它们;
  • 可以快速的构建任何复杂的合成视图,重用它们为一个单一的组件。

合成控件的示例

在ApiDemos示例中,演示了SpeechView,它继承了LinearLayout,并创建了一个组件,用于显示谈话中的引号。相关的类
见:

samples/ApiDemos/src/com/example/android/apis/view/List4.java

samples/ApiDemos/src/com/example/android/apis/view/List6.java

List4示例截图,见:

image

List6示例截图,可以点击条目,出现内容,见:

image

 

修改已存在的视图类型

如果已存在的视图组件已经和你的需求相差不远,你可以只是简单的扩展该组件,只覆盖需要改变的行为。

比如示例中的NotePad应用(platforms/android-1.5/samples/NotePad)。

效果如下:

image

在文本框视图组件(EditText)基础上,增加了横线。

 

抱歉!评论已关闭.