View
extends Objectimplements Drawable.Callback KeyEvent.Callback AccessibilityEventSource
Class Overview
这个类代表了构建用户交互组件的基本单元。一个View是一块绘制和接收用户事件的位于屏幕上的长方形区域。它是widgets的基础(widgets指用户交互组件)。而子类ViewGroup则是布局的基础(布局:用于容纳其他Views,并定义他们的布局属性)。
Developer Guides 开发向导
想要知道更多,参阅User Interface开发向导。
Using Views 使用
所有处于窗口中的view都被安排在一颗树上(即只有一个根节点)。你可以从代码或者特定的XML布局文件中来添加views。这儿有很多特殊view的子类,他们具有控制或者显示文本,图片及其他内容的能力。
一旦你创建views的树,你可能希望实现几个典型的通用操作:
设置属性:可在构建时用XML定义。
设置焦点:调用requestFocus()
设置监听器:可通知获得或者失去焦点。子类具有更多监听事件
设置可见性:使用setVisibility(int)设置可见性
Implementing a Custom View 实现自定义的View
实现自己的View,覆盖下面框架的几个回调方法即可。你不需要重写所有的方法。事实上,你可用从重写onDraw(android.graphics.Canvas)开始
Category | Methods | Description |
---|---|---|
Creation | Constructors 构造体 | 有一种从代码创建或者从布局文件膨胀时调用,另一种是粘贴及应用布局文件中定义的属性。 |
| 当其子类完成膨胀时调用. | |
Layout |
| 当决定view和它的孩子的尺寸时调用. |
| Called when this view should assign a size and position to all of its children. | |
| Called when the size of this view has changed. | |
Drawing |
| Called when the view should render its content. |
Event processing 事件 处理 |
| Called when a new hardware key event occurs. |
| Called when a hardware key up event occurs. | |
| Called when a trackball motion event occurs. | |
| Called when a touch screen motion event occurs. | |
Focus 焦点 |
| Called when the view gains or loses focus. |
| Called when the window containing the view gains or loses focus. | |
Attaching 依附 |
| Called when the view is attached to a window. |
| Called when the view is detached from its window. | |
| Called when the visibility of the window containing the view has changed. |
IDs
Views有很多整形id与其相关。这些id被分配到XML布局文件中,用于寻找特定的view。通用模式如下:
- 定义一个布局文件并赋予其唯一ID
<Button android:id="@+id/my_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/my_button_text"/>
- 在Activity中的onCreate回调方法中找到这个button.
Button myButton = (Button) findViewById(R.id.my_button);
视图的ID并不需要在整个树中唯一,但是最佳实践是让它在你搜索的那一部分树上唯一。
Position 位置
View是长方体,它为坐标指的是距离左/上 距离,计量单位是像素。
一种可能的检索view位置的方式是调用 和 方法。前者返回 左(X),后者返回 上(Y)。返回值都是相对于父容器的。举个例子,当getLeft()返回20,它意味着它距离它的直接父容器左边的距离为20。
额外的,一些便利类可以让你减少计算,例如getRight()
和 getBottom().
Size, padding and margins 尺寸,填充 和 边缘
The size of a view is expressed with a width and a height. A view actually possess two pairs of width and height values.
尺寸代表了宽度和高度,这儿有两种标准:
第一种被称做:测量宽度和测量高度。这些尺寸定义了views想要在它的父容器中有多大。通过调用getMeasuredWidth()
and getMeasuredHeight()
取得这些尺寸。
第二种就是 宽度和高度,也叫做 绘制宽度 和绘制高度。这些尺寸定义了,在布局完成后绘制时,实际绘制在屏幕上的实际尺寸。通过调用 getWidth()
and getHeight()
获得这些尺寸。
For instance, a left padding of 2 will push the view's content by 2 pixels to the right of the left edge. Padding can be set using the setPadding(int, int, int, int)
or setPaddingRelative(int, int, int, int)
method and queried by calling getPaddingLeft()
, getPaddingTop()
, getPaddingRight()
, getPaddingBottom()
, getPaddingStart()
, getPaddingEnd()
.
在绘制尺寸时,view是将填充也计算在内了的。填充以像素表示,具有左、上、右、下四个部分。填充使得view的内容能够以指定的像素进行偏移。举个例子,左边2的填充意味着view的内容向右边移动了2个像素。你可以使用下面这些方法:
setPadding(int, int, int, int)
, setPaddingRelative(int, int, int,int)
,
getPaddingLeft()
, getPaddingTop()
,
getPaddingRight()
, getPaddingBottom()
, getPaddingStart()
, getPaddingEnd()
.
尽管view定义了填充,但是没有对 边缘(margins) 提供任何支持,它被放在了 ViewGroup
和ViewGroup.MarginLayoutParams
中了。
Layout 布局
布局有两个过程:测量和布局。测量实现了measure(int, int),它自顶向下的遍历了view树。在递归过程中,每个view被分配了特定的尺寸。在测量完成后,每个view将存储他的测量值。第二步在 中,它也是自顶向下的.在这一步中,每个父容器都使用在上一步得到的值来计算子view的位置。
在view完成了measure方法返回后,getMeasuredWidth()
和getMeasuredHeight()值必须被设置。一个view的测量宽度和测量高度值必须遵循父view的限制。这可以保证,在测量后,所有的父亲都能够接受子View的测量。父View可能不止一次调用子的measure()。举个例子,父view可能测量子View使用的是不确定的尺寸,来找出它想要多大,然后再一次使用实际值调用measure(),如果所有子类未加限制的尺寸过大或者太小
测量经过两个类计算尺寸。View.MeasureSpec类用于告知父类他们想怎样被测量和定位。基本的LayoutParams类只是描述他们想要的高度和宽度。对于每一个维度:可以指定为以下几个值:
- 确切的数字
- MATCH_PARENT,这意味着它们想和父容器一样大(减去padding)
- WRAP_CONTENT,这意味着他们只想和他们包含的内容一样大(加上padding)
有不同的LayoutParams子类对应着不同的ViewGroup的子类。举个例子,绝对布局拥有可以添加X和Y的布局子类。
测量空间(MeasureSpecs)用于自上而下的推送需求。测量空间可以是下面三种的一种:
- 未指定的(UNSPECIFIED):这用于父容器绝对子类视图尺寸。举个例子,线性布局可能通过调用 子类的measure()方法,通过设定高度为UNSPECIFIED以及240确切的宽度来发觉子类在给予240像素宽度时,子视图需要的高度。
- 确切的(EXACTLY):这用于父容器强加一个确切的数给其子类。子类必须使用这个尺寸,这保证了所有其子孙视图都会适配这个值。
- 最大的(AT_MOST):这用于父容器强加一个最大值给其子类。子类必须保证自己和子孙视图适配这个值。
为了初始化布局,调用requestLayout() 。这个方法典型的应用是视图认为自身不在适配当前的边界。
Drawing 绘制
绘制是通过遍历和将视图插入到无效区域(未被使用区域)来完成的。由于树的遍历是有顺序的,这意味着父节点会先绘制前面的,然后才是它的兄弟。如果你给一个VIEW设定了背景drawable,那view将会在为你先绘制,然后才调用它的onDraw()
方法。
注意:在非无效区域的视图是不会被框架所绘制的。
为了强制完成绘制工作,调用invalidate()
.
Event Handling and Threading 事件处理和线程
一个view基本的周期如下:
1. 一个事件到来并被分配给合适的view。这个view将事件通知给任何注册的监听者。
2. 在处理事件中,视图的边界可能需要改变,调用requestLayout() 。
3. 相似的,如果在处理事件过程中需要更新界面,调用invalidate() 。
4. 如果requestLayout()或者invalidate()被调用了,框架将会处理 测量,布局和绘制工作。
注意:整个视图树是单一的线程。当你调用任何视图的方法时,你总是处于UI线程中。如果你在工作线程中想要更新视图的状态,你应该使用Handler。
Focus Handling 焦点处理
框架将会例行的响应用户输入的响应。这包含了当视图移除或者隐藏起来,新的视图出现时等改变。视图在方法isFocusable()中表明了他们想要获得焦点的意愿。去改变一个视图的焦点,调用setFocusable(boolean),而不管它是否能够获得焦点。当在触屏模式下,视图表明他们是否愿意通过isFocusableInTouchMode()
获得焦点,或者通过 setFocusableInTouchMode(boolean)
改变焦点。
焦点移动是基于给定方向的最近邻居算法。在很少的情况下,算法和开发者想要的效果不一致。在这些情况下,你才需要显示的在XML布局文件中覆盖这些属性。
nextFocusDown
nextFocusLeft
nextFocusRight
nextFocusUp
为了让特殊的VIEW获得焦点,调用requestFocus()。
Touch Mode 触摸模式
当用户经由类似D-pad的直接案件导航到用户接口,这有必要聚焦到用户所见的输入控件上。如果设备有触摸能力,那么,所有的用户都以触摸方式完成交互,那么高亮或者给予特定视图焦点就不再有必要。这种模式也就是“触摸模式”。
对于具有触摸能力的设备,一旦用户触摸屏幕,设备即进入触摸模式。从这一点往后,只有isFocusableInTouchMode()为真的视图才会继续拥有焦点,例如编辑小部件。其他的视图是可触摸的,例如按钮,在被触摸时,将不会获得焦点。他们仅仅是响应用户的点击行为。
Any time a user hits a directional key, such as a D-pad direction, the view device will exit touch mode, and find a view to take focus, so that the user may resume interacting with the user interface without touching the screen again.
任何用户直接的按键,例如直接 D-pad,视图设备将会推出点击模式,然后发现一个View来获得焦点,然后用户可以恢复交互直到用户再次点击。
触摸模式可在活动间传播。调用isInTouchMode()来观察设备当前是否处于触摸模式。
Scrolling 滚动
框架对于需要滚动内部内容的视图提供基本的支持。这包含了跟踪X和Y的滚动偏移,以便绘制滚动条的位置。更多细节见 scrollBy(int, int)
, scrollTo(int, int)
, 和 awakenScrollBars()
Tags 标记
不同于ID,标记并不用于标识视图。标记用于为VIEW添加额外的信息片段。他们最常用于作为view自身便利的数据存储,而无需放在额外的数据结构中。
Properties 属性
View类曝光了ALPHA属性,作为几种平台相关的属性,例如TRANSLATION_X
和 TRANSLATION_Y。和他们的属性既可以以属性方式,也可以用 setter/getter方法。
Animation 动画
自安卓3.0开始,更好使用动画的方式是使用android.animation
包中的API。这些基于动画的类改变了视图实际的属性,例如透明度和偏移X(alpha
and translationX
)。
Security 安全
有时候确认一个行为是用户完全的行为是有毕业的,例如权限的确认,执行一次购买,或者点击广告。不幸的是,恶意程序可能尝试欺骗用户无意识的执行这些行为。作为一种补救措施,框架提供一种可用语提交视图访问敏感功能的点击过滤机制。
为了使用点击过滤,调用setFilterTouchesWhenObscured(boolean)
或者设置 。当能够使用时,框架将会放弃 。作为结果,当有Toast,对话框或者窗口出现在视图窗口的上方时,视图将不会接受点击事件。
对于更多细力度的安全控制,考虑覆盖onFilterTouchEventForSecurity(MotionEvent) 方法来实现你自己的安全策略。参考:FLAG_WINDOW_IS_OBSCURED