Android 如何 绘制View

来源:互联网 发布:剑网三眉间雪捏脸数据 编辑:程序博客网 时间:2024/05/21 09:23
 Android画的操作是由Framework层来进行处理的,整个 draw是从根View开始的,ViewGroup向子View发出 draw的请求,然后子View负责自己重画它们的invalid区域。Drawing一个Layout必须通过两个步骤:
       1. 测量。measure() 从根节点到叶子节点依次测量,这样每个View都会存有各自的dimension.在我们的程序种我们可以重写onMeasure来设置更为精确的content大小,重写完后必须调用setMeasureDimension来存储View的宽和高 。 
       2.布局。layout也是从父节点到子节点,父节点根据刚才传递进来的measure信息来拜访它们的子节点。
       当一个视图的measure()方法返回时,它的getMeasuredWidth()和getMeasuredHeight() 值必须被设置,以及所有
这个视图子节点的值。一个view的measure的宽度和高度值必须符合父视图的限制。这确保在度量过程之后,所有父节点接受所有它们的子节点的度量值。一个父视图可能会在其子视图上多次调用measure()方法。比如,父视图可能会通过未指定的尺寸调用measure来找到它们的大小,然后使用实际数值再次调用measure(),如果所有子视图未做限制的尺寸总合过大或过小(也即是,如果子视图之间不能对各自占据的空间达成共识的话,父视图将会干预并且使用第二个过程的规则)。
       View.MeasureSpec 用于子View告诉父View它们想如何被测量和怎么放置。而 LayoutParams则是描述了View的宽和高是多少。对于每一个区域可以指定如下的值:  
  •  一个准确的数值。
  • ·FILL_PARENT,这意味着视图想和父视图一样大(减掉填充padding)。
  •  WRAP_CONTENT,这意味着视图只想有刚好包装其内容那么大(加上padding)。
      对于不同的ViewGroup子类,有相应的LayoutParams子类。比如,相对布局RelativeLayout有它自己的LayoutParams子类,这包含了能够让子视图横向和竖向居中显示的能力。
       
      度量规格(MeasureSpecs)被用来沿着树从父到子的下传度量需求。一个MeasureSpecs可以是下面三种模式之一:
  • UNSPECIFIED:父视图来决定其子视图的理想尺寸。比如,一个线性布局可能在它的子视图上调用measure() on its child,通过设置其高度为UNSPECIFIED 以及一个宽度为EXACTLY 240,来找出这个子视图在给定240像素宽度的情况下需要显示多高。
  •  EXACTLY:父视图用来给子视图强加一个准确的尺寸。子视图必须使用这个大小,并确保其所有的后代将适合这个尺寸。
  • AT_MOST:这被父视图用来给子视图强加一个最大尺寸。子视图必须确保它自己以及所有的后代都适合这个尺寸。


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Drawing
画图的过程是通过遍历树来展示View有效部分来实现的。因为遍历树是有序的,所以父节点优先于
子节点绘制出来,兄弟节点则通过在树中的顺序来展示框架不会在有效区域之外画图,
并且会画好Views的背景。可以通过invalidate()方法来执行绘图。

Event Handing and Threading
视图的生命周期如下:
-当一个事件发生时会被派发到适当的View中,视图处理事件并且通知所有的监听器
-在处理事件的过程中,如果视图的边界发生了变化,那么View会调用requestLayout()方法
-相似的情况下,当视图的可视性发生了变化,那么需要调用invalidate()方法
-不管requestLayout()或则invalidate()方法被调用,框架都会重新测绘和布局,并且在树中合适的地方画上view
注意:整个视图树是在一个线程内处理的,因此调用任何方法时,必须在UI现场内处理,如果其他线程内需要更新
view的视图状态,则需要通过Handler类

Focus Handing
框架会处理常规的焦点移动以应对用户输入作出反应。包括试图移动或隐藏或新视图可见时改变焦点。视图通过
isFocusable()方法提示其是否需要焦点。调用setFocusable(boolean)方法来设置视图是否需要焦点
焦点移动基于一种算法:找到指定方向上最近的邻居。在极少情况下,算法的结果与开发人员期望的不一样。
可以通过在布局文件中设置如下四个属性来明确定义属性指向:nextFocusDown,nextFocusLeft,nextFocusRight
nextFocusUp.要强制一个视图获取焦点,调用requestFocus()方法。

Touch Mode
当用户操作方向键时最好是活的焦点的组件一些动作来提示用户那个组件获得了焦点。当设备拥有触摸功能时,用户
可以通过触摸来选定组件。这个模式叫做"Touch mode".
在一个有触摸能力的设备中,一旦用户触摸了屏幕,设备就会进入到"touch mode"。只有isFocusableInTouchMode()
为true的组件才可以活的焦点,比如editing组件,其他的比如buttons不会获得焦点,它只关心点击操作。
任何时候用户点击了方向键,设备就会退出touch模式而进入到按键模式
可以在Activitys中通过isInTouchMode()方法来确定设备是否在触摸模式中。

Scrolling
框架对期望在内部滚动其内容的视图提供了基本的支持,包括跟踪X和Y的滚动偏移来画滚动条。可通过srolllBy(int,int)
,scrollTo(int,int)和awakenScrollBars()来了解更多细节

Tags
与ID不同,标枪不用来识别视图。标签是可以关联到视图上的额外信息。通常用来方便在视图中存储与视图相关的数据,
而不是存放在独立的结构中。

Animation
通过setCurrentAnimation(Animation)或startAnimation(Animation)把一个动画对象加到View中。动画可以改变View的
比例,旋转,平移以及ALPHA。如果有子视图,则该动画会影响整个视图树。当动画开始,框架负责重画视图,知道动画结束。

Security
大部分时候应用应该可以确认动作所需要的所有内容比如获得访问的权限,购买东西以及点击广告链接。
不幸的是,一些恶意的应用会视图欺骗用户去操作这些动作,用户不经意的就会操作隐藏在view后面的动作。
作为一种补救,框架提供了一种轻的过滤框架来提高比较敏感模块的安全性。
可以通过setFilterTouchesWhenObscured(boolean)或则android:filterTouchesWhenObscured来启用过滤机制。
启用后,框架会在用户启动另外一个view的时候锁定原先的view。比如当有警告,对话或其他视窗在view上面展示时
就不在允许点击view了。
在更小的控制颗粒度下。可以重写onFilterTouchEventForSecurity(MotionEvent)来实现你自己的安全策略。
也可以查看FLAG_WINDOW_IS_OBSCURED.

Constants
int  |GONE    |视图不展示,并且不占用任何布局空间

int  |VISIBLE|视图时可见的

interfaces
public static interface OnClickListener:用于响应View的点击事件
     public Methods
     abstract void onClick(View v):处理点击事件的方法。




原创粉丝点击