原文地址: http:/(删掉我)/www.vogella.com/tutorials/AndroidCustomViews/article.html#customviews
如下是我的翻译:
1..自定义视图
1.1. Default views
Android framework提供了几个默认的视图,但开发者也可以自定义自己的视图在他们的app中。
其中基本的类是view
1.2. How Android draws the view hierarchy
一旦activity获得焦点,它必须提供给系统它的布局层次中的根节点。之后系统开始绘制。
绘制是从布局的根节点开始的。依据他们所声明的顺序,换言之,父层是先于它的子层开始绘制的,而子层先于子子层绘制(递归)...
绘制布局要经过两个层次:
1)通过测量(measuring pass)实现measure(int,
int)方法,它自上而下遍历视图层。每个视图存储它的测量。
2)通过布局(layout
pass)实现layout(int, int, int, int),它自上而下遍历视图层。在此阶段,每个布局管理器负责定位它的所有子视图。它使用计算过的大小(在measuring
pass中)。
注意:测量与布局这两个阶段通常一块发生。布局管理器通常会使用measuring
pass几次。
view或者activity可以调用requestLayout()来触发measure
and layout pass。
在measure
and layout pass之后,视图绘制自身,通过调用view中 invalidate()方法,这个操作被触发。
1.3. Reasons for creating views
可以自定义自己的交互。
1.4. Responsibility of views
视图是负责测量,布点和绘画自己和他们的子元素(如果是一个ViewGroup)。它还负责保存自己的UI状态和处理触摸事件。
1.5. Ways of creating custom views
自定义的视图大致有两类:复合视图和定制的视图。所以可以通过以下两种方式来创建自定义视图:1)复合视图(Compound views)2)自定义视图(Custom views):a.继承一个已经存在的视图。b.继承视图类。
1.6. Using new views in layout files
视图可以被应用于布局文件中。你必须使用完全且规范的名称。举个例子:<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button" /> <de.vogella.android.ownview.MyDrawView android:id="@+id/myDrawView1" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout>
1.7. Create screenshots (Images) of views
每个视图类支持它当前显示图像的创建。举个例子:<pre name="code" class="java"># Build the Drawing Cache view.buildDrawingCache(); # Create Bitmap Bitmap cache = view.getDrawingCache(); # Save Bitmap saveBitmap(cache); view.destroyDrawingCache();
复合视图也称复合组件(Compound Components),它可以基于已有的view为viewgroup所配置。
复合视图也允许你添加自定义的api去更新,查询该视图的状态。
你可以定义一个布局文件,并将其分配给您的复合视图。在你的复合视图的实现您预定义的视图交互。你需定义一个布局文件,并继承相应的视图组类。在这个类中你可以填充(inflate)的布局文件和实施视图连接逻辑。
3. 创建自定义视图
3.1. Creating custom views
你可以通过继承view或者其子类来创建。使用onDraw()来绘制视图,在此方法中,你可用Canvas对象来执行绘制。(想画个线,圆,图...)。如果视图被重新绘制,你可以调用
invalidate()
来触发调用该视图的onDraw()方法。你可以使用2D
Canvas API.去绘制视图。
3.2. Measurement
布局管理器调用视图的onMeasure()方法。该视图从布局管理器接收的布局参数。布局管理器负责决定其所有子项的大小。
视图必须调用setMeasuredDimenstion(int,
int)。
3.3. Defining custom layout managers
通过拓展ViewGroup,你可以实现自己的布局管理器。这允许你实现更加高效,或者当前android系统中尚不存在的布局管理器。自定义布局管理器可以覆盖onMeasure()和OnLayout()方法,并指定其子项的计算。你可以在你拓展的类中使用内部类来存储布局参数。(举个例子:LinearLayout的内部类:LinearLayout.LayoutParams)
4. Life cycle
4.1. Life cycle events related to the window
视图有几个生命周期挂钩。该onAttachedToWindow()被调用一次窗口是可用的。
当视图是从其父移除(如果父连接到一个窗口)的onDetachedFromWindow()被使用。举个例子:当activity被回收,或者在ListView中的view被回收。
onDetachedFromWindow()被用作停止动画和清理资源。
4.2. Traversal life cycle events
遍历生命周期事件包括动画,测量,布置和绘制。
所有视图必须知道如何测量和布局本身。该requestLayout()方法调用告诉视图来测量和布局本身。由于这种操作可能会影响其他视图的布局。
onMeasure()
方法决定视图及其孩子的大小。在它返回前,必须通过调用setMeasuredDimension()来设置其尺寸。
onLayout()
摆放视图,其基于onMeasure()
的方法
4.3. Activity life cycle
视图不可访问activity的生命周期事件。如果视图希望得到有关这些事件,你应该在你的activity的生命周期方法调用该视图所创建一个接口。
5. Define additional attributes for your custom Views
可以为你的视图定义额外的属性。你可以在res/values文件夹下定义属性文件attrs.xml。下面是个例子:<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="ColorOptionsView"> <attr name="titleText" format="string" localization="suggested" /> <attr name="valueColor" format="color" /> </declare-styleable> </resources>在你的布局文件中去使用这些属性,你需要在xml首部声明他们。下面是个例子
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" <!-- define new name space for your attributes --> xmlns:custom="http://schemas.android.com/apk/res/com.vogella.android.view.compoundview" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <!-- Assume that this is your new component. It uses your new attributes --> <com.vogella.android.view.compoundview.ColorOptionsView android:layout_width="match_parent" android:layout_height="?android:attr/listPreferredItemHeight" custom:titleText="Background color" custom:valueColor="@android:color/holo_green_light" /> </LinearLayout>下面的示例显示了组件如何访问这些属性。
package com.vogella.android.view.compoundview; import android.content.Context; import android.content.res.TypedArray; import android.util.AttributeSet; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; public class ColorOptionsView extends View { private View mValue; private ImageView mImage; public ColorOptionsView(Context context, AttributeSet attrs) { super(context, attrs); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Options, 0, 0); String titleText = a.getString(R.styleable.Options_titleText); int valueColor = a.getColor(R.styleable.Options_valueColor, android.R.color.holo_blue_light); a.recycle(); // more stuff } }下面一些相关且比较好的文章:
http://blog.csdn.net/loongggdroid/article/details/17515113