View 翻译

Position

View的形状就是一个矩形,一个View有一个Location属性,用一对原点在左上角的坐标表示,View还有两个dimension属性,用width和height表示。Location属性和dimension属性的单位都是像素。

可以通过调用getLeft() 和 getTop()函数来获取lodcation属性的值。前者返回矩形的左侧或者说X轴坐标。后者返回矩形的顶部或者说Y轴坐标,这两个方法返回的坐标都是这个View相对于其父容器的相对坐标。例如,当getLeft()返回20,意思是说这个View位于距其直接父容器左边缘右边20像素处。

另外还有几个方便的方法,使用它们可以避免不必要的计算,它们是 getRight() 和 getBottom()。这两个方法返回矩形的右边缘和底部的坐标。例如,调用getRight()就相当于这样计算:getLeft()+getWidth()(关于size详情请看Size段落)

Size, padding and margins

View的大小用width和height来表示。实际上一个View有两对宽高值。

第一对值是我所知道的measured width和measured height。这两个尺寸就是一个View在它的父容器里想要多大的空间(详见Layout段落)。该measured尺寸可以通过调用getMeasuredWidth() 和 getMeasuredHeight()方法获取。

第二对值简称为width和height,有时又叫做drawing width和drawing height。这两个尺寸就是View经过布局后在显示屏上实际绘制大小。这两个值可以和measured with,measured height大小不一样,但这并不是必须的。你可以通过调用getWidth() 和 getHeight()来获取它们的值。

View在测量measured 尺寸的时候会把Padding考虑在内。Padding是指View的上、下、左、右部分的像素值。Padding可以通过一个像素值来指定View的内容的偏移量。例如,一个值为2的left Padding可以把View的内容放在(View的)左边缘右边两个像素处。可通过setPadding(int, int, int, int)方法和getPaddingLeft()getPaddingTop()getPaddingRight()getPaddingBottom()方法来设置和获取Padding值。

尽管可以指定View的Padding,但是它没有提供任何对Margin的支持。但是,view groups提供了这样的支持,你可以参考ViewGroup和ViewGroup.MarginLayoutParams以获得更多的信息。

Layout

布局分为两个过程:测量过程和布局过程。测量过程在measure(int,int)中实现,是一个自上而下遍历View树的过程。在这个递归过程中,每一个View都把尺寸规格向下传递。到这个过程的结束时,每个View都已经存储了自己的尺寸。第二个过程发生在 layout(int, int, int, int) 方法中,也是自上而下的过程。在这个过程中每个父容器根据在测量过程中计算的尺寸来放置子控件。

当一个View的measure()函数返回时,它的getMeasuredWidth()和getMeasureHeight()方法的返回值必须是已经设置好了,相应这个View的子View也必须遵循这个规则。一个View的measured width 和measured height必须遵守父节点对它的尺寸约束。这就保证了在测量过程结束后所有的父节点都能接受它所有子节点的尺寸。一个父节点可能多次调用它子节点的measure()方法。例如:父节点不限制的情况下先调用一次它所有子节点的measure()方法来看看它们一共想要多大的尺寸,所有子节点在没有限制条件下的尺寸要求的总和如果太大或者太小,那么父节点就会用实际数字(译注:就是加上限制条件)再次调用measure()

测量过程使用量个类来传递尺寸信息。ViewGroup.LayoutParams被View用来告诉它的父节点它想要被如何测量和放置。而基类LayoutParams 只是描述View想要多宽多高。具体每个尺寸规格,它可以指定如下值:

  一个精确值

  FILL_PARENT,意味着view想尽量和它的父节点一样大。(减去父节点的Padding)

  WRAP_CONTENT,意味着view想要适应其内容大小的尺寸(加上自己的Padding)

不同的ViewGroup子类有对应的LayoutParams子类。例如:RelativeLayout拥有对应的LayoutParams子类,这个LayoutParams的子类有在水平、竖直方向让View居中放置的能力。

MeasureSpecs 用于自树的父节点到子节点向下传递限制规则。它可以为如下三种模式之一:

  UNSPECIFIED:父节点用该值来限制其子节点所渴望的大小。例如,一个LinearLayout可以调用其子节点的measure()函数,并把高度规定为UNSPECIFIED而宽度规定为EXACTLY 240,来看看在宽度240个像素的规定下,这个子节点想要多高。

  EXACTLY:父节点用该值强加一个精确的值给它的子节点。这个子节点必须用这个尺寸,并保证它(这个子节点)所有的子节点都在这个尺寸范围内。

  AT_MOST:父节点用该值强加一个最大值给它的子节点。这个子节点必须保证它和它的子节点必须在这个范围之内。

初始化布局,可以调用 requestLayout()方法。该方法是视图在认为自身不在适合当前边界大小时,通常调用的方法。

Drawing

绘制过程就是通过遍历这个树,并渲染其中每一个与invalid region相交的View,因为是按顺序遍历树,也就是说父节点先于它的子节点绘制(先绘制的会处于后话的下一层显示)兄弟节点根据它们在树中出现的顺序绘制。如果你为View设置了一个背景Drawable,那么这个View会在回调它的onDraw()方法之前绘制Drawable。

强制View绘制,可以调用invalidate()方法。

Event Handling and Threading

View的基本周期如下:

1.产生的事件分发给相应的View。View收到事件并通知监听器。

2.如果在事件的处理过程中,如果Viwe的边界需要改变,View 将调用requestLayout()

3.同样,在事件处理过程中, 如果View的外观需要改变,View就会调用 invalidate()

4.如果调用了 requestLayout() 或 invalidate(),系统框架会适当的执行测量,布局、和绘制动作。

 注意:正个View 树是单线程,你调用任何View的方法时必须在UI线程中。如果你正在其他线程中工作又想在这个线程中更新一个View的状态,那么你应该用一个Handler来处理。

框架会维护处理焦点移动的程序来处理用户相应的输入。这个包括因为View被移除或者隐藏引起的焦点改变,或者是因为你一个新的View变为可见。可以通过isFocusable() 方法来查看View是否愿意获取焦点。通过setFocusable(boolean)方法来设置View是否能获取焦点。在触摸模式(参看下文)View通过isFocusableInTouchMode() 标示它是否仍然愿意获取焦点,并且可以通过setFocusableInTouchMode(boolean)来改变这一属性。

焦点移动基于一种给定方向找最近位置的算法。,这种默认的算法极少情况匹配不到开发者想要的行为,在这种情况下你可以用布局文件中的这些属性提供精确指示:

 nextFocusDown
 nextFocusLeft
 nextFocusRight
 nextFocusUp

想让特定View获取焦点就调用requestFocus()方法。

Touch Mode

当用户使用像D-pad这样的方向键来导航一个用户接口时,必须让类似按钮的控件获取焦点,让用户知道它就是当前会获取输入的控件。如果设备具有触摸功能,这样用户就可以通过触摸它来进行交互,也不需要总是要给一个特定的View设置高亮或者焦点了。这就是所谓的触摸模式。

对于具有触摸功能的设备,一旦用户触摸屏幕,这个设备就进入了触摸模式。然后,只有像文本编辑这样 isFocusableInTouchMode()返回ture的控件才能获取焦点,而其他诸如按钮这样的可以触摸的控件,当触摸它的时候不会获取焦点;它们只是通知点击监听器而已。

用户在任何时候点击像D-pad这样的方向键,设备就会退出触摸模式,并找出一个View让其获取焦点,用户就可以不适用触摸屏来继续进行交互。

触摸模式的状态由 Activity来维护。调用 isInTouchMode()方法查看设备当前是否处于触摸模式。

Scrolling

系统框架为那些想在内部滚动其内容的View提供了一个基础支持,这个支持不但包括跟踪X,Y方向的滚动位移,还包括绘制滚动条的机制。详情请看 scrollBy(int, int),scrollTo(int, int), 和 awakenScrollBars()

Tags

不同于ID,tag并不是用来标示View的。它其实是一个和View有关的外部数据片段。他们通常是利于用来在View内部存储和View有关的数据,而不是另外单独存储。

Properties

View类提供了一个ALPHA属性,就诸如TRANSLATION_X and TRANSLATION_Y这样与变形(transform-related)相关的属性一样。这些属性都能以Property的形式并用setter/getter方法(获取或者设置)(例如,用setAlpha(float)设置ALPHA属性)。这些属性都可用来设置View与渲染相关属性的固定值。这些属性和方法也可以协同基于Animator(Animator-based)的动画一起使用。详见Animation章节。

Animation

从3.0开始,实现View动画推荐使用android.animation包提供的API。这些基于Animatior(Animator-based)的动画可以改变View对象的属性,例如alpha和translationX属性。相对于3.0之前的版本,它不仅仅描述了View的显示方式。特别是ViewPropertyAnimator类是使View的这些属性产生动画效果更有效更简单的方式。

做为一个选择,你也可以用3.0之前的动画类来实现View的动画。你可以通过setAnimation(Animation) 或者 startAnimation(Animation)给一个View附加一个Animation 对象。动画可以对View逐渐进行缩放、旋转、移动,改变透明度的操作。如果被附加的View有子View。那么这个动画会做用于这个View下的整个子树。当动画开始后,系统框架会重绘相应的View直到动画结束。

 

 

 

 

 

 

posted @ 2012-09-11 10:54  zhaoke5421  阅读(232)  评论(0编辑  收藏  举报