android.view.View类简介(一)

来源:互联网 发布:php 构造函数 编辑:程序博客网 时间:2024/06/14 15:06

类概述:

View类代表用户界面组件的最基本组成模块。View占据屏幕的一个矩形区域,并负责绘制和事件处理。View是widgets中的基类,用来开发交互式UI组建(按钮,输入框等)。ViewGroup子类是layouts的基类,ViewGroup用来容纳其他的Views(或其他的ViewGroup)并定义布局属性。

开发人员指南:

想要了解如何通过View类来开发你的应用的用户界面,请阅读用户界面开发人员指南

使用Views:

窗口中的所有视图都被安排在单个树结构中。我们可以从代码中添加视图或在一个或多个XML布局文件中指定视图的树结构。有许多专门的view子类用于展示文本,图片或其他内容。
一旦你已经建立了视图的树结构,你可能希望使用下面几个典型的通用操作:
设置属性:例如设置TextView需要显示的内容,可以获得的属性和方法在不同的子视图中是不一样的,在创建时已知的属性可以在XML布局文件中进行设置。
设置焦点:框架会处理焦点移动来响应用户输入,我们可以调用requestFocus()来使某个视图强制获得焦点。
设置监听器:View允许设置监听器,当特定事情发生时,监听器中的特定方法会被调用。例如,所有的view都允许设置一个监听器用来感知该view获得或失去焦点,我们通过setOnFocusChangeListener(android.view.View.OnFocusChangeListener),其他的子视图会提供更具体的监听器,例如,Button开放一个监听器用来通知客户端该Button是否被点击。
设置可见性:你可以通过setVisibility(int)来设置是否隐藏或显示当前视图
提示:安卓框架负责measuring,laying out以及drawing views。你可以不用调用view视图的这些相关方法除非你自己实现的一个ViewGroup。

实现一个自定义视图:

想要实现一个自定义视图,我们通常会重写一些安卓框架在所有views中调用的方法,我们通常不用重写所有的方法,事实上,你可以通过仅重写onDraw(android.graphics.Canvas)方法来实现自定义视图
Constructors(构造器):构造函数被调用的一种形式是我们在代码中创建视图,另一种形式是我们inflate布局文件中定义的视图,第二种形式会解析并应用布局文件中的所有属性。
onFinishInflate():当XML中的视图和它的所有子视图被inflate后调用该方法
onMeasure(int,int):决定当前视图和它的所有孩子的大小
onLayout(boolean,int,int,int,int):当前视图在为孩子分配大小和位置时调用该方法
onSizeChanged(int,int,int,int):当前视图的大小改变时调用该方法
onDraw(android.graphics.Canvas):当view渲染它的内容时调用该方法
onKeyDown(int,KeyEvent):硬键盘事件发生时调用该方法
onKeyUp(int,KeyEvent):硬键盘事件发生时调用该方法
onTrackballEvent(MotionEvent):当轨迹球运动事件发生时调用该方法(没用过)
onTouchEvent(MotionEvent):当触摸屏事件发生时调用该方法
onFocusChanged(boolean,int,android.graphics.Rect):视图获得/失去焦点时调用该方法
onWindowFocusChanged(boolean):window获得/失去焦点时调用该方法
onAttachedToWindow():view绑定到window时调用
onDetachedFromWindow():view从window脱离时调用
onWindowVisibilityChanged(int):当window的可见性变化时调用

IDs:

Views可能拥有一个相关联的整数id值,id值主要在XML文件中被分配,用于查找view树中的特定view,一个常见的模式是:
在layout文件中定义一个按钮,并分配一个唯一的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 myButton = (Button) findViewById(R.id.my_button);
视图ID不需要在整个树结构中是唯一的,一个好的做法是保证在你想要搜索的部分树结构中是唯一的

Position:

view的几何形状是矩形,view会有固定的显示位置,体现为左上角的坐标,以及两个维度(宽度和高度),位置和维度的单位为像素。

我们可以调用getLeft()、getTop()、getRight()和getBottom()方法来获得view的位置信息,这些方法返回的位置信息都是相对于父视图的,例如,当getLeft返回值为20,代表该view的左边缘在父视图左边缘的右侧20像素的位置。另外,调用getRight相当于调用getLeft + getWidth。

Size,padding and margins

view的大小用宽度和高度来表示,一个view实际上拥有两对宽度和高度值。

第一对是measured width和measured height,这两个维度定义了一个view在parent中想要获得的大小(查看Layout获得更多信息),measured dimensions(测量维度)可以通过调用getMeasuredWidth()和getMeasuredHeight()获得。

第二对是width和height,或者drawing width和drawing height,这两个维度定义了view在layout之后的drawing(绘制)过程中应该在屏幕显示的实际大小,这两个值可能和measured值不同,width和height可以通过调用getWidth()和getHeight()获得。

为了测量它的尺寸,view还要考虑它的填充信息,填充信息会以像素的形式体现在视图的上下左右四个部分,padding可以用来设置view内容的偏移量(像素为单位),例如,padding of 2 会使视图的内容举例view的左边界2个像素值,padding信息可以通过setPadding(int,int,int,int)或setPaddingRelative(int,int,int,int)方法来设置,通过getPaddingLeft(),getPaddingTop(),getPaddingRight(),getPaddingBottom(),getPaddingStart()和getPaddingEnd()方法来获取。

尽管view可以定义padding,但是它没有提供对margin的支持,然而,viewgroup可以支持margin,参考ViewGroup和ViewGroup.MarginLayoutParams来获取更多信息。

Layout

Layout是一个两步的过程:measure过程和layout过程,measure过程通过measure(int,int)实现,该过程是一个从上到下遍历view树的过程,在递归过程中每个视图向子树推送大小限制信息,在测量过程的结尾,每个视图都存储了它的测量值,第二个过程发生在layout(int,int,int,int)函数调用中,该过程也是从上至下的过程,在这个过程中,每个父类都会通过在measure过程中得到的大小值来放置它的所有孩子。

当view的measure方法返回时,getMeasureWidth()和getMeasureHeight()必须被设置,以及该视图的所有后羿。视图的measured width和measured height必须遵守父视图给的大小限制,这保证了在测量过程的结尾,所有的父类都接受子类的测量信息,一个父视图可能会不止一次调用measure(),例如,父视图可能使用unspecified策略来测量子类来检测他们需要多大的空间,如果以upspecified策略得到孩子需要的空间过大或过小,这是就需要通过确切的数值来再次调用measure()。

measure过程使用两个类来表达尺寸信息,View.MeasureSpec类用于决定如何测量和放置view视图,LayoutParams类用于描述当前视图想要多大的空间,对于各个维度,Layoutparams可以使用如下的一个:

  1. 一个确切的数值
  2. MATCH_PARENT,表示该view想要和父视图一样大小的空间(去除padding)
  3. WRAP_CONTENT,表示该view想要可以容纳它的内容的空间大小
针对ViewGroup的不同子类,LayoutParams存在对应的子类,例如,AbsoluteLayout对应的LayoutParams可以添加X值和Y值

MeasureSpecs被父类用于向子类推送大小限制信息,MeasureSpec可以使用如下的三种模式:

  1. UNSPECIFIED:用于父类决定子视图想要的空间大小,例如,一个LinearLayout可能调用子视图measure()并设置height为UNSPECIFIED,width为EXACTLY(240),用来判断在给子视图240像素的宽度时,子视图希望拥有的高度。
  2. EXACTLY:用于父视图传递给子视图一个固定大小信息,子视图必须使用这个大小,而且子视图要保证它的所有后羿必须在这个大小范围内
  3. AT_MOST:用于父视图传递给子视图一个大小的限制信息,子视图必须保证它和它的所有后羿必须在这个大小范围内
想要初始化一个layout,调用requestLayout(),这个方法被view调用,当该视图确信它已经不再适合当前的区域边界。

Drawing

Drawing通过遍历整个树结构,并记录需要更新的视图的绘制命令,在此之后,整个视图树的绘制命令会被递交给屏幕,并剪切掉最新被销毁的区域,形成绘制树。
绘制树按顺序被记录和绘制,父视图会在子视图之前(或之后)被绘制,兄弟节点按在视图树中出现的先后顺序被绘制,如果你设置了view的背景信息,那么view会在调用onDraw之前绘制背景信息。子视图的绘制顺序可以通过重写ViewGroup中的custom child drawing order和View中的setZ(float)来实现。
想要强制view重画,调用invalidate()。

Event Handling and Threading

视图的基本周期如下:

  1. 事件发生并被分配到恰当的视图,视图处理该事件并通知监听器
  2. 如果在处理事件的过程中,视图的边界信息发生改变,则当前view需要调用requestLayout()
  3. 同样的,在处理事件的过程中,视图的界面需要改变,视图需要调用invalidate()
  4. requestLayout()或invalidate()中的任何一个被调用,框架都会以恰当的方式measuring,laying out和drawing视图树
Note:整个视图树都在一个单独的线程中,当你调用方法改变view时,你必须在UI线程中,如果你在其他线程中工作并想要在当前线程中改变view,你需要使用Handler

Focus Handling

框架会处理常规的焦点移动来响应用户输入,这包括当视图被移除或隐藏时改变焦点位置,或当新的视图available时改变焦点位置,View通过isFocusable()方法来表明是否想要获得焦点,想要改变一个视图是否可以获得焦点,调用setFocusable(boolean),当处在touch mode下的view想要表明是否仍然想要获得焦点,可以调用isFocusableInTouchMode(),调用setFocusableInTouchMode(boolean)方法设置是否可以获得焦点。

想要一个view获得焦点,调用requestFocus()方法

Touch Mode

当用户通过方向键(例如D-pad)浏览用户界面时,我们有必要使可操作的单元(例如按钮)获得焦点,这样用户可以看到那些单元需要输入。如果设备拥有触摸功能,用户通过触摸屏幕来和界面交互,这就没必要让特定的单元一直高亮或得到焦点,这促使了一个新的叫touch mode的交互模式。

对于可以触摸的设备,一旦用户触摸屏幕,设备就会进入touch mode,从此时开始,只有isFocusableInTouchMode()返回值为true的视图会得到焦点,比如编辑框,其他可以触摸的视图(按钮)并不会获得焦点,他们只会触发click listener

任何时候用户点击方向键,例如D-pad,设备都会退出touch mode,touch mode由Activity维护,我们可以通过调用isInTouchMode()方法来判断设备是否正处于touch mode中

Scrolling

框架提供了对视图的基本支持以便视图可以在内部滚动它的内容,这包括跟踪X和Y方向的滚动偏移量以及绘制scrollbar(滚动条)机制,用户可以查看scrollBy(int,int),scrollTo(int,int)和awakenScrollBars()来获得更多信息。

Tags

和ID不同,tags并不用于标识view,tags基本上是一个可以和视图关联的额外的标签,它们主要用作一个便利设备来存储和view相关的数据,而不是把数据放在一个单独的结构中。

Properties

view提供了ALPHA以及一些和转换相关的属性,例如,TRANSLATION_X和TRANSLATION_Y,这些属性我们可以从属性文件中获得,也可以从名字相似的setter、getter方法中获得(例如setAlpha(float)对应于ALPHA),这些属性可以被用于设置视图中和渲染相关的属性的持久状态,这些属性和方法同样可以被用于连接Animator-based animation。

Animation

从anroid3.0开始,首选的animating view的方式是使用android.animation包中的APIs,这些动画相关的类改变view类的实际属性,例如alpha和translationX,这些行为和3.0之前的Animation-based class形成了鲜明对比,之前的类只能控制view如何被绘制,尤其是,ViewPropertyAnimator类使animating这些视图属性变的相当简单和高效。

另外,你可以使用3.0之前的版本来animate视图如何呈现,你可以通过调用setAnimation(Animation)或startAnimation(Animation)将一个Animation绑定到一个视图,animation随着时间的推移可以更改view的scale、translation和alpha,如果view拥有子视图,animation会影响以该视图为根的子树,当动画开始后,框架会处理重画相应的视图知道动画结束。

Security

有些时候应用程序有必要能够证实一个action是在用户完全了解并同意的情况下进行的,例如获取一个权限,完成一次交易或者点击某个广告,不幸的是,一些恶意程序会欺骗用户执行这些动作,as a remedy(作为一个补救措施),框架提供了一个触摸过滤机制,该机制提高了视图开放敏感功能的安全性。

0 0
原创粉丝点击