【Android】View

一个Android应用程序中,用户界面通过ViewViewGroup对象构建。Android中有很多种Views和ViewGroups,他们都继承自View类。View对象是Android平台上表示用户界面的基本单元。

View类:
extends Object implements Drawable.Callback   KeyEvent.Callback   AccessibilityEventSource

这个类表示用户界面组件的基本构建块,一个View占据屏幕上的一个矩形区域,并负责绘图和事件处理。View类是widgets的基类,widgets用于创建交互式UI组件(buttons、text fields等)。View类的直接子类ViewGroup类是layouts的基类,layouts是不可见的容器用户保持其他Views或者其他ViewGroups和定义它们的布局属性。(This class represents the basic building block for user interface components. A View occupies a rectangular area on the screen and is responsible for drawing and event handling. View is the base class for widgets, which are used to create interactive UI components (buttons, text fields, etc.). TheViewGroup subclass is the base class for layouts, which are invisible containers that hold other Views (or other ViewGroups) and define their layout properties.)

一个View对象是一个数据结构,它的属性存储屏幕上一个特定矩形区域的布局参数内容。一个View对象处理它自己的测度、布局、绘图、焦点改变、滚动、键/手势等与屏幕上矩形区域的交互。作为用户界面中的对象,View也是与用户交互的一个点且交互事件接收器。

All of the views in a window are arranged in a single tree. You can add views either from code or by specifying a tree of views in one or more XML layout files. There are many specialized subclasses of views that act as controls or are capable of displaying text, images, or other content.所有的View都被组织在一棵树里面,如下:

Position

The geometry of a view is that of a rectangle. A view has a location, expressed as a pair of left and top coordinates, and two dimensions, expressed as a width and a height. The unit for location and dimensions is the pixel.(所以是个组件一定是长方形的(按钮倒是可以做成椭圆的),组件的定位是以左上角的坐标(称为location)以及长宽(称为dimension)来定义的,单位是像素)。

It is possible to retrieve the location of a view by invoking the methods getLeft() and getTop(). The former returns the left, or X, coordinate of the rectangle representing the view. The latter returns the top, or Y, coordinate of the rectangle representing the view. These methods both return the location of the view relative to its parent. For instance, when getLeft() returns 20, that means the view is located 20 pixels to the right of the left edge of its direct parent.

In addition, several convenience methods are offered to avoid unnecessary computations, namely getRight() and getBottom(). These methods return the coordinates of the right and bottom edges of the rectangle representing the view. For instance, calling getRight() is similar to the following computation: getLeft() + getWidth() (see Size for more information about the width.)

(以上的函数都可以返回Android的位置以及大小,单位是像素)

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.

The first pair is known as measured width and measured height. These dimensions define how big a view wants to be within its parent (see Layout for more details.) The measured dimensions can be obtained by calling getMeasuredWidth() and getMeasuredHeight().

The second pair is simply known as width and height, or sometimes drawing width and drawing height. These dimensions define the actual size of the view on screen, at drawing time and after layout. These values may, but do not have to, be different from the measured width and height. The width and height can be obtained by calling getWidth() and getHeight().

组件的尺寸是有两套的,一套是希望的尺寸大小,而一套是实际的尺寸大小,两者可能是不一样的。

To measure its dimensions, a view takes into account its padding. The padding is expressed in pixels for the left, top, right and bottom parts of the view. Padding can be used to offset the content of the view by a specific amount of pixels. 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) method and queried by calling getPaddingLeft(),getPaddingTop()getPaddingRight()getPaddingBottom().

Padding是边缘相对于内容的,而Margin是边缘相对于其他组件边缘的。

Even though a view can define a padding, it does not provide any support for margins.组件可以设置自己的padding,但是无法设置自己的margin,实际写代码的时候margin是在Layoutparams里面进行配置。

Layout

Layout is a two pass process: a measure pass and a layout pass. The measuring pass is implemented in measure(int, int) and is a top-down traversal of the view tree. Each view pushes dimension specifications down the tree during the recursion. At the end of the measure pass, every view has stored its measurements. The second pass happens in layout(int, int, int, int) and is also top-down. During this pass each parent is responsible for positioning all of its children using the sizes computed in the measure pass.(Layout分为两个过程,一个是测量的过程,测量完毕之后,每个view都存储好了自己的尺寸,第二个过程就是布局过程,父View安排子View的位置,两个过程都是自上往下的)

布局使用的长宽单位:

1 an exact number
2 MATCH_PARENT, which means the view wants to be as big as its parent (minus padding)
3 WRAP_CONTENT, which means that the view wants to be just big enough to enclose its content (plus padding).

Drawing

Drawing is handled by walking the tree and rendering each view that intersects the invalid region. Because the tree is traversed in-order, this means that parents will draw before (i.e., behind) their children, with siblings drawn in the order they appear in the tree. If you set a background drawable for a View, then the View will draw it for you before calling back to its onDraw() method.绘图是从上至下(从父到子)绘制界面

Note that the framework will not draw views that are not in the invalid region.To force a view to draw, call invalidate().

 不在合法区域的view是不可见的,可以使用invalidate强制绘图。
 

Event Handling and Threading(界面更新机制)

The basic cycle of a view is as follows:

  1. An event comes in and is dispatched to the appropriate view. The view handles the event and notifies any listeners.
  2. If in the course of processing the event, the view's bounds may need to be changed, the view will call requestLayout().
  3. Similarly, if in the course of processing the event the view's appearance may need to be changed, the view will call invalidate().
  4. If either requestLayout() or invalidate() were called, the framework will take care of measuring, laying out, and drawing the tree as appropriate.

Note: The entire view tree is single threaded. You must always be on the UI thread when calling any method on any view. If you are doing work on other threads and want to update the state of a view from that thread, you should use a Handler.

Focus Handling

The framework will handle routine focus movement in response to user input. This includes changing the focus as views are removed or hidden, or as new views become available. Views indicate their willingness to take focus through the isFocusable() method. To change whether a view can take focus, callsetFocusable(boolean). When in touch mode (see notes below) views indicate whether they still would like focus via isFocusableInTouchMode()and can change this via setFocusableInTouchMode(boolean).(可以通过Foucus来控制组件是否接受输入事件)

Focus movement is based on an algorithm which finds the nearest neighbor in a given direction. In rare cases, the default algorithm may not match the intended behavior of the developer. In these situations, you can provide explicit overrides by using these XML attributes in the layout file:

1 nextFocusDown
2 nextFocusLeft
3 nextFocusRight
4 nextFocusUp

可以通过以上四个函数来移动焦点。To get a particular view to take focus, call requestFocus().可以使用requestFocus()来迫使一个View获取焦点。

Touch Mode

When a user is navigating a user interface via directional keys such as a D-pad, it is necessary to give focus to actionable items such as buttons so the user can see what will take input. If the device has touch capabilities, however, and the user begins interacting with the interface by touching it, it is no longer necessary to always highlight, or give focus to, a particular view. This motivates a mode for interaction named 'touch mode'.

如果使用键盘控制焦点,那么很有必要显示到底是哪个组件目前获得焦点,可以获得输入。但是如果是进行触摸事件,就没有必要高亮显示某个组件。这种通过触摸进行交互的模式称为“触摸模式”。

For a touch capable device, once the user touches the screen, the device will enter touch mode. From this point onward, only views for whichisFocusableInTouchMode() is true will be focusable, such as text editing widgets. Other views that are touchable, like buttons, will not take focus when touched; they will only fire the on click listeners.

对于可触摸设备而言,一旦触摸屏幕就会进入触摸模式,只有当isFocusableInTouchMode是真的时候,组件才会被焦点,并且触发Click监听。

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.

一旦按下方向键就会退出触摸模式。

Scrolling

The framework provides basic support for views that wish to internally scroll their content. This includes keeping track of the X and Y scroll offset as well as mechanisms for drawing scrollbars. See scrollBy(int, int)scrollTo(int, int), and awakenScrollBars() for more details.

Tags

Unlike IDs, tags are not used to identify views. Tags are essentially an extra piece of information that can be associated with a view. They are most often used as a convenience to store data related to views in the views themselves rather than by putting them in a separate structure.

原文地址:https://www.cnblogs.com/lqminn/p/2728014.html