现在的位置: 首页 > 综合 > 正文

Android中View绘制视图

2013年06月21日 ⁄ 综合 ⁄ 共 4263字 ⁄ 字号 评论关闭

视图(View)是一个矩形区域,它负责这个区域里的绘制和事件处理。视图类是Android用户界面的基础类之一。视图组(ViewGroup)是视图的子类,是一个容器,专门负责布局。视图组本身没有可绘制的元素。

        开发用户界面可以先阅读开发者向导的用户界面(User Interface)部分。

        该文章包含:

                声明布局

                创建菜单

                公用布局对象

                AdapterView绑定数据

                处理UI事件

                应用风格(styles)或主题(themes)

                自定义组件

                Android怎样绘制视图

使用视图

        一个窗口中的所有视图是一个树形结构。你可以通过代码创建视图,也可以通过XML布局文件来创建。文本、图像都是视图的派生类。

        视图和其子类具有如下共同特性:

         设置属性,例如设置文本视图的文本。不同的子类具有不同的属性,这些属性在设计时可以设定。

         设置焦点,为了响应用户输入,Android框架会处理焦点的转移。要把焦点转移到特定视图上,可以使用requestFocus()函数。

         设置监听器(listener),视图可以让客户端设置监听器,特定事件发生时这些监听器会收到通知。例如,视图得到或失去焦点时,会收到关于焦点的通知。你可以使用setOnFocusChangeListener(View.OnFocusChangeListener)来注册监听器。例如,按钮Button就有一个点击事件的监听器。

         设置可见性,用setVisibility(int)显示和隐藏视图。

        Android框架负责视图的测量(measuring)、布局(laying out)、绘制(drawing)。一般情况你不需要调用这些方法,除非你重载ViewGroup这样的布局类。

自定义视图

        自定义视图需要重载下列一些方法。

        

IDs
        视图有整数ID,这些ID一般在XML布局文件中分配。一般的样式

        定义一个按钮并分配一个唯一ID

         <Button id="@+id/my_button"

             android:layout_width="wrap_content"

             android:layout_height="wrap_content"

             android:text="@string/my_button_text"/>

        onCreate函数创建视图时,查找一个按钮

                Button myButton = (Button) findViewById(R.id.my_button);

        视图ID并不要求是全局唯一,不过为了便于搜索最好在视图树的局部是唯一。

位置

        视图在几何上就是一个矩形,左上角的left和top坐标定位,宽width和高height表示尺寸大小,单位是像素pixel。

        使用getLeft()和getTop()获取左上角位置,这些位置都是相对于父视图。

        此外还有几个方便方法getRight()和getBottom()获得右边和底部位置。

尺寸,内间距padding,外间距margins

        视图的尺寸用宽和高表示,一个视图有两对宽高值。

        第一对宽高值是测量值(measured width, measured height),测量值是子视图相对父视图的尺寸大小期望值。可以用getMeasuredWidth()和getMeasuredHeight()获取。

        第二对宽高值是实际值,实际尺寸是视图完成布局后绘制时用到的值。

        测量尺寸大小时要计算内间距padding,内间距表示了视图内各个子控件到父控件上下左右四条边的间距。

        普通视图不支持外间距,只有ViewGroup支持。详见ViewGroup.MarginLayoutParams。

布局Layout

        布局分两个阶段(pass):测量阶段(measure pass)和布局阶段(layout pass)。测量阶段在measure(int, int)方法中实现,整个过程就是从上至下的视图树遍历。在这个递归过程,每个视图都提供尺寸大小描述。测量阶段的最后,每个视图都保存了自己的测量结果。布局阶段在layout(int, int, int, int)函数中实现,这也是一个从上至下的过程。在布局阶段,每个父视图使用测量阶段的估算值为子视图安排位置和大小。

        当视图的measure()方法返回后,它和它的子控件的测量值都已经计算出来了。子控件的测量值都要考虑父视图的区域限制,这就保证了在测试阶段结束时,每个父视图能接受其所有子控件的测量结果。子控件的measure()方法可能被多次调用。例如,包含了尺寸不确定的子控件,父控件会对每个子控件调用一次measure()方法,然后再对尺寸明确的子控件调用measure()方法,这样作是为了保证没有确切尺寸的子控件不至于太大或太小。

        测量阶段会用到两个类:View.MeasureSpec和LayoutParams。视图使用View.MeasureSpec类来表明自己所期望的位置和测量方式,LayoutParams则是来表明自己期待的大小。

        它们都可以使用下面的值:

                确切的数值

                MATCH_PARENT,在父控件里尽可能的大(除去内间距padding值)。

                WRAP_CONTENT,尽可能的小,只要能容纳自己的子控件即可(加上内间距padding值)。

        LayoutParams有一些派生类,会被视图组ViewGroup用到。例如,AbsoluteLayout包含了X和Y值,用来描述布局时的绝对位置。

        MeasureSpecs在父视图向子控件询问布局期望时会被用到。它有三种模式:

        UNSPECIFIED,未指定,父控件向子控件询问布局期望值。例如,线性布局类LinearLayout想知道子控件在宽为240的时候高的期望值,便可以调用子控件的measure()方法,并在传递参数中指定高为UNSPECIFIED,宽为确定值240像素。

        EXACTLY,确定值,父控件指定子控件的尺寸,并要求该子控件的子控件也必须适应这个尺寸。

        AT_MOST,最大值,父控件指定子控件的最大尺寸,并要求该子控件的子控件也必须适应这个尺寸。

        当视图想父控件再次对自己执行布局操作时,可以调用requestLayout(),一般在视图的尺寸发生改变时会有这种需求。

绘制Drawing

        绘制按照视图树的顺序执行。视图绘制时会先绘制子控件。如果视图的背景可见,视图会在调用onDraw函数之前绘制背景。

        强制重绘,可以使用invalidate()。

事件处理和线程

        事件的基本流程如下:

                1。事件分配给相应视图,视图处理它,并通知相关监听器。

                2。操作过程中如果发生视图的尺寸变化,则该视图用调用requestLayout()方法,向父控件请求再次布局。

                3。操作过程中如果发生视图的外观变化,则该视图用调用invalidate()方法,请求重绘。

                4。如果requestLayout()或invalidate()有一个被调用,框架会对视图树进行相关的测量、布局和绘制。

        注意,视图树是单线程操作,直接调用其它视图的方法必须要在UI线程里。跨线程的操作必须使用句柄Handler。

焦点处理

        框架处理焦点的转移,来响应用户输入。isFocusable()函数表示视图是否能接受焦点。setFocusable(boolean)函数可以改变视图能否接受焦点。触摸屏模式(Touch Mode)的相关函数是isFocusableInTouchMode()和setFocusableInTouchMode(boolean)。

        焦点转移按照就近算法。按哪个方向就近可以在XML布局文件中配置。

         nextFocusDown

         nextFocusLeft

         nextFocusRight

         nextFocusUp

        视图请求焦点可以使用requestFocus()。

触摸屏模式Touch Mode

        当用户使用方向键盘(D-pad)操作时,当前控件需要聚焦高亮来提示用户。但是对于触摸屏,就不再需要这种高亮了。我们管这种模式叫触摸屏模式。

        用户一接触触摸屏设备就进入触摸屏模式。从此,只有isFocusableInTouchMode()函数返回true的视图才能聚焦高亮,例如文本框。而按钮就不需要在触摸屏模式下高亮了。

        用户一接触方向键,界面就退出触摸屏模式,并找到当前哪个视图需要聚焦高亮,以便用户在键盘模式下也能确认正在操作的控件。

        触摸屏模式是全局性的,跨Activity的。isInTouchMode()函数可以获得是否在触摸屏模式下。

滚动Scrolling

        视图本身支持滚动,包括XY的偏移位置和滚动条的绘制。

标签Tag

        标签用于储藏对象

动画Animation

        视图可以附加Animation对象,setAnimation(Animation)设置动画,startAnimation(Animation)启动动画。Animation可以按时间轴改变视图的位移、缩放大小、旋转角度和透明度,来制造动画效果。Animation的效果是包括了该视图的子视图。动画启动后,框架就负责重绘该视图。

抱歉!评论已关闭.