官网-View对象:https://developer.android.google.cn/reference/android/view/View.html
public class View
extends Object
implements Drawable.Callback, KeyEvent.Callback, AccessibilityEventSource
该类表示用户界面组件的基本构建块。视图占据屏幕上的一个矩形区域,负责绘图和事件处理。View是小部件的基类,用于创建交互式UI组件(按钮、文本字段等)。ViewGroup子类是布局的基类,布局是不可见的容器,其中包含其他视图(或其他ViewGroup)并定义它们的布局属性。
Developer Guides
有关使用该类开发应用程序的用户界面的信息,请参阅用户界面开发人员指南。
Using Views
窗口中的所有视图都排列在一棵树中。您可以从代码中添加视图,也可以通过在一个或多个XML布局文件中指定视图树来添加视图。视图有许多专门的子类,它们充当控件,或者能够显示文本、图像或其他内容。
一旦你创建了一个视图树,通常有几种常见的操作你可能希望执行:
设置属性:例如设置TextView的文本。在视图的不同子类中,可用属性和设置它们的方法会有所不同。注意,在构建时已知的属性可以在XML布局文件中设置。
设置焦点:框架将处理响应用户输入的移动焦点。要强制焦点到特定视图,请调用requestFocus()。
设置监听器:视图允许客户端设置监听器,当视图发生有趣的事情时,会通知监听器。例如,所有视图将允许您设置侦听器,以便在视图获得或失去焦点时得到通知。您可以使用setOnFocusChangeListener(android.view.View.OnFocusChangeListener)注册这样一个侦听器。其他视图子类提供了更专门化的侦听器。例如,按钮公开侦听器,以便在单击按钮时通知客户机。
Set visibility:可以使用setVisibility(int)隐藏或显示视图。
注意:Android框架负责测量、布局和绘制视图。除非实际实现了ViewGroup,否则不应该调用自己对视图执行这些操作的方法。
Implementing a Custom View(自定义视图)
要实现自定义视图,通常首先要为框架对所有视图调用的一些标准方法提供覆盖。您不需要覆盖所有这些方法。实际上,您可以从覆盖onDraw(android.graphics.Canvas)开始。
IDs
视图可能具有与其关联的整数id。这些id通常在布局XML文件中分配,用于在视图树中查找特定的视图。一个常见的模式是:
在布局文件中定义一个按钮,并为其分配一个惟一ID。
<Button android:id="@+id/my_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/my_button_text"/>
从活动的onCreate方法中找到按钮
Button myButton = findViewById(R.id.my_button);
视图id不必在整个树中都是惟一的,但最好确保它们至少在您正在搜索的树中是惟一的。
Position(配置)
视图的几何形状是矩形的几何形状。视图有一个位置,表示为一对左侧和顶部坐标,还有两个维度,表示为宽度和高度。位置和尺寸的单位是像素。
可以通过调用getLeft()和getTop()方法来检索视图的位置。前者返回表示视图的矩形的左侧或X坐标。后者返回表示视图的矩形的顶部或Y坐标。这些方法都返回视图相对于其父视图的位置。例如,当getLeft()返回20时,这意味着视图位于其直接父类的左边缘的右侧20个像素处。
此外,还提供了一些方便的方法来避免不必要的计算,即getRight()和getBottom()。这些方法返回表示视图的矩形的右下角的坐标。例如,调用getRight()类似于下面的计算:getLeft() + getWidth()(有关宽度的更多信息,请参见Size)。
Size, padding and margins
视图的大小用宽度和高度表示。视图实际上拥有两对宽度和高度值。
第一对被称为测量宽度和测量高度。这些维度定义了视图在其父视图内的大小(有关详细信息,请参见布局)。可以通过调用getmeasure width()和getmeasure height()获得测量的维度。
第二对简单地称为宽度和高度,有时也称为绘图宽度和绘图高度。这些维度定义了屏幕上视图的实际大小,在绘图时和布局后。这些值可能与测量的宽度和高度不同,但不一定一定要不同。可以通过调用getWidth()和getHeight()获得宽度和高度。
要度量它的尺寸,视图需要考虑它的填充。填充以视图的左、上、右和下部分的像素表示。填充可以用特定数量的像素来偏移视图的内容。例如,左填充2将视图的内容推到左边缘的右侧2个像素。填充可以使用setPadding(int, int, int, int)或setPaddingRelative(int, int, int, int, int)方法进行设置,并通过调用getPaddingLeft()、getPaddingTop()、getPaddingRight()、getPaddingBottom()、getPaddingStart()、getPaddingEnd()查询。
即使视图可以定义填充,它也不提供对边距的任何支持。然而,视图组提供了这样的支持。参考ViewGroup和ViewGroup。MarginLayoutParams获取更多信息。
Layout(布局)
布局是一个两步的过程:一个度量步骤和一个布局步骤。度量遍历是在measure(int, int)中实现的,它是视图树的自顶向下遍历。在递归期间,每个视图都将维度规范下推到树中。在度量传递结束时,每个视图都存储了它的度量值。第二步是布局(int, int, int, int),也是自顶向下的。在此传递过程中,每个父进程负责使用度量传递中计算的大小来定位它的所有子进程。
当视图的measure()方法返回时,必须设置它的getmeasure width()和getmeasure height()值,以及该视图所有后代的值。视图的测量宽度和测量高度值必须尊重视图父视图施加的约束。这保证了在测试结束时,所有的父母都接受他们孩子的所有测试。父视图可以对其子视图多次调用measure()。例如,父级可以用未指定的维度度量每个子级一次,以确定它们想要多大,然后如果所有子级的无约束大小的和太大或太小,则用实际的数字再次调用measure()。
度量传递使用两个类来传递维度。MeasureSpec类被视图用来告诉它们的父母它们希望如何被度量和定位。基本LayoutParams类只描述了视图的宽度和高度的大小。对于每个维度,可以指定其中一个:
an exact number,一个确切的数量
MATCH_PARENT,这意味着视图要和其父视图一样大(减去填充)
WRAP_CONTENT,这意味着视图要足够大,以封装其内容(加上填充)。
LayoutParams的子类用于ViewGroup的不同子类。例如,AbsoluteLayout有自己的LayoutParams子类,它添加X和Y值。
度量方法用于将需求从父级推到子级。一项措施可以在三种模式之一:
UNSPECIFIED(未指定的):父视图使用它来确定子视图的所需维度。例如,LinearLayout可以调用其子视图上的measure(),并将高度设置为未指定的值,宽度正好为240,以确定子视图的宽度为240像素时的高度。
EXACTLY(完全正确):这是由父类用来给子类施加一个精确的大小。孩子必须使用这个大小,并确保所有后代都符合这个大小。
AT_MOST:父进程使用它来为子进程设置最大大小。孩子必须保证他和他所有的后代都能适应这个尺寸。
要初始化布局,请调用requestLayout()。当一个视图认为is不再适合其当前范围时,通常会调用该方法。
Drawing(绘图)
绘图是通过遍历树并记录需要更新的任何视图的绘图命令来处理的。在这之后,整个树的绘制命令被发送到screen,剪切到新损坏的区域。
这棵树很大程度上是按顺序记录和绘制的,而亲本则是在此之前绘制的。他们的孩子和兄弟姐妹按照他们在树上出现的顺序画出来。如果您为视图设置了一个背景drawable,那么视图将在调用其onDraw()方法之前绘制它。可以使用ViewGroup中的ViewGroup#setChildrenDrawingOrderEnabled(boolean)和视图上的setZ(float)自定义Z值}覆盖子绘制顺序。
若要强制视图绘图,请调用invalidate()。
Event Handling and Threading(事件处理和线程)
视图的基本周期如下:
事件进入并被分派到适当的视图。视图处理事件并通知任何侦听器。
如果在处理事件的过程中,视图的边界可能需要更改,那么视图将调用requestLayout()。
类似地,如果在处理事件的过程中可能需要更改视图的外观,则视图将调用invalidate()。
如果调用了requestLayout()或invalidate(),框架将根据需要度量、布局和绘制树。
注意:整个视图树是单线程的。在调用任何视图上的任何方法时,必须始终处于UI线程上。如果您正在处理其他线程,并且希望从该线程更新视图的状态,则应该使用处理程序
Focus Handling(焦点处理)
该框架将处理响应用户输入的常规焦点移动。这包括在视图被删除或隐藏时,或在新视图可用时更改焦点。视图表明它们愿意通过isfocavailable()方法进行关注。要更改视图是否可以获取焦点,请调用setfocavailable (boolean)。当处于触摸模式(见下面的注释)时,视图指示他们是否仍然希望通过isFocusableInTouchMode()进行聚焦,并且可以通过setFocusableInTouchMode(boolean)进行更改。
焦点移动是基于在给定方向上找到最近邻居的算法。在极少数情况下,默认算法可能与开发人员的预期行为不匹配。在这些情况下,您可以使用布局文件中的这些XML属性提供显式覆盖:
nextFocusDown nextFocusLeft nextFocusRight nextFocusUp
要获得一个特定的视图来获取焦点,请调用requestFocus()。
Touch Mode(触感模型)
当用户通过方向键(如D-pad)在用户界面中导航时,有必要将焦点放在可操作的项(如按钮)上,这样用户就可以看到需要输入什么。但是,如果设备具有触摸功能,并且用户开始通过触摸与界面交互,则不再需要总是突出显示或关注特定的视图。这激发了一种名为“触摸模式”的交互模式。
对于具有触摸功能的设备,一旦用户触摸屏幕,设备将进入触摸模式。从现在开始,只有isFocusableInTouchMode()为真的视图才是可聚焦的,比如文本编辑小部件。其他可触摸的视图,如按钮,在触摸时不会聚焦;它们只会触发on click侦听器。
每当用户按下方向键,例如D-pad方向,视图设备就会退出触摸模式,并找到一个视图进行对焦,这样用户就可以在不再次触摸屏幕的情况下继续与用户界面交互。
触摸模式状态是跨活动维护的。调用isInTouchMode()查看设备当前是否处于触摸模式。
Scrolling(滚动)
框架为希望在内部滚动其内容的视图提供了基本支持。这包括跟踪X和Y滚动偏移量以及绘制滚动条的机制。有关详细信息,请参见scrollBy(int, int)、scrollTo(int, int)和awakenScrollBars()。