Android的View和ViewGroup分析
1. 概念
Android中的View与我们曾经理解的“视图”不同。在Android中,View比视图具有更广的含义,它包括了用户交互和显示,更像Windows操作系统中的window。
ViewGroup是View的子类。所以它也具有View的特性,但它主要用来充当View的容器,将当中的View视作自己的孩子,对它的子View进行管理,当然它的孩子也能够是ViewGroup类型。
ViewGroup(树根)和它的孩子们(View和ViewGroup)以树形结构形成了一个层次结构,View类有接受和处理消息的功能,android系统所产生的消息会在这些ViewGroup和 View之间传递。
2. Android的窗体系统
Android的窗体系统是Client/Server模式的,我在这里仅仅讲窗体系统的client(图1)。 我们所提到的概念:View,ViewGroup。DecorView,ViewRoot都是存在于窗体系统的Client端。
Android中的Window是表示Top Level等顶级窗体的概念。
DecorView是Window的Top-Level View。这个View能够称之为主View,DecorView会缺省的attach到Activity的主窗体中。
ViewRoot建立了主View(DecorView)与窗体系统Server端的通讯桥梁, ViewRoot是 Handler的子类,即它事实上是个Handler。它接受窗体系统server端的消息并将消息投递到窗体系统的client(图1)。然后消息就从client的主View往其以下的子View传递。直到消息被全然处理掉为止。
图1 窗体系统的client
DecorView实际上是一个ViewGroup。
在依存关系上来讲。对单个主窗体来讲,DecorView是Top-Level View。View并非关注的重点,重要的是我们须要知道消息分发路径是建立在什么关系上的。View的成员变量mParent用来管理View上级关系的。而ViewGroup顾名思义就是一组View的管理,于是在ViewGroup构建了焦点管理和子View节点数组。
这样通过View的mParent和ViewGroup的mChildren构建了Android中View直接的关系网。
3. View的介绍
(1) 事件和绘制
绘制流程:
绘制依照视图树的顺序运行。视图绘制时会先绘制子控件。
假设视图的背景可见,视图会在调用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()。
(2) 成员介绍
protected ViewParent mParent;
mParent用于记录它的父亲,就是我们前面提到的ViewGroup。
protected OnClickListener mOnClickListener;
mOnClickListener是click事件的回调接口.
大家常常使用的setOnClickListener(OnClickListener listener):
public void setOnClickListener(OnClickListener I) {
if (!isClickable()) {
setClickable(true);
}
mOnClickListener =I;
}
能够看出,mOnClickListener事实上就是保存我们在应用程序中定义的OnClickListener接口的。
public void draw(Canvas canvas)
这个函数用于渲染View和它的孩子,我们不应该在子类对它进行override。
protected void onDraw(Canvas canvas)
我们一般override此函数来实现自己的绘制操作。
IWindowSession getWindowSession() {
return mAttachInfo != null ? mAttachInfo.mSession : null;
}
函数getWindowSession()用户得到窗体系统Client端和server端通讯的接口IWindowSession。这是一个AIDL接口,android系统中的跨进程通讯就是用AIDL接口实现的。
public final void layout(int l, int t, int r, int b)
此函数用于确定View和其子View的尺寸和位置,它的调用发生在onMeasure之后。
protected void onLayout(boolean changed, int left, int top, int right, int bottom)
此函数在layout调用完毕后运行,View的子类一般override此函数。并在函数中对其每一个孩子调用layout方法。
public View getRootView()
此函数用于得到View层次结构的top-level View,即上文中提到的DecorView。
public final void measure(int widthMeasureSpec, int heightMeasureSpec)
此函数用户找出View的大小,它的參数widthMeasureSpec、heightMeasureSpec是其父亲传递给它的,这2个參数是View找出其大小时的限制条件,事实上真正的精确大小确定是由onMeasure()完毕的。onMeasure由measure函数调用。
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
此函数測量View并依据其内容来决定View的高和宽,它应该被子类override以实现大小的精确測量。在onMeasure中我们必须调用View.setMeasuredDimension(int, int)来保存測量得到的大小,高和宽分别被保存在View.mMeasuredHeight和View.mMeasureWidth中。
public boolean onKeyUp(int keyCode, KeyEvent event)
此函数会在键盘按键释放后被调用,但前提是View必须获得焦点。
public boolean onTouchEvent(MotionEvent event)
此函数用于响应触摸屏事件。
public void invalidate()
此函数将调用onDraw,强制重绘。
public void requestLayout()
当某些东西发生改变后。当前View层次结构无效了。调用此函数对View的层次结构进行又一次布局。
4. ViewGroup介绍
ViewGroup继承于View,它能够包括其它的View,就像一个View的容器。我们能够调用其成员函数addView()将View当作孩子放到ViewGroup中。
我们常常使用的LinearLayout、relativeLayout等都是ViewGroup的子类。ViewGroup类中有一个内部类ViewGroup.LayoutParams。我们常常使用LayoutParams的子类来构造布局參数。
我们也能够自己定义自己的布局,以方便日后使用和维护,这时我们就须要继承ViewGroup类并在派生类中重写ViewGroup的一些方法,以下是一个简单的样例:
public class MyViewGroup extends ViewGroup {
public MyViewGroup(Context context) {
super(context);
initChilren(context); //向容器中加入孩子
}
private void initChilren (Context context) {
Button aBtn = new Button(context);
this.addView(aBtn);
Button bBtn = new Button(context);
this.addView(bBtn);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b)
{
//对容器的孩子进行布局。
………………
………………
child.measure(r - l, b - t);
child.layout(0, 50, child.getMeasuredWidth(), child .getMeasuredHeight() + 50);
………………
………………
}
}
作者:gemmem
Android的View和ViewGroup分析的更多相关文章
- android自定义View&自定义ViewGroup(上)
一般自定义view需要重写的方法 void onMeasure(int widthMeasureSpec, int heightMeasureSpec) void onSizeChanged(int ...
- 【转载】Android 中 View 绘制流程分析
创建Window 在Activity的attach方法中通过调用PolicyManager.makeNewWindo创建Window,将一个View add到WindowManager时,Window ...
- Android中View和ViewGroup介绍
1. 概念Android中的View与我们以前理解的“视图”不同.在Android中,View比视图具有更广的含义,它包含了用户交互和显示,更像Windows操作系统中的window. ViewGro ...
- Android原理View、ViewGroup
Android的UI界面都是由View和ViewGroup及其派生类组合而成的.其中,View是所有UI组件的基类,而ViewGroup是容纳这些组件的容器,其本身也是从View派生出来的.Andro ...
- Android界面View及ViewGroup学习 《转载》
View及ViewGroup类关系 Android View和ViewGroup从组成架构上看,似乎ViewGroup在View之上,View需要继承ViewGroup,但实际上不是这样的. View ...
- android 自定义 view 和 ViewGroup
---恢复内容开始--- ViewGroup的职能为:给childView计算出建议的宽和高和测量模式 :决定childView的位置:为什么只是建议的宽和高,而不是直接确定呢,别忘了childVie ...
- android重写view和viewgroup的区别
重写view: View类一般用于绘图操作,重写它的onDraw方法,但它不可以包含其他组件,没有addView(View view)方法. 重写viewgroup: ViewGroup是一个组件容器 ...
- Android的View类介绍-android的学习之旅(十三)
view概述 android绝大部分UI组件都放在android.view和android.widght包中,android的虽有UI组件都继承了View类. View类还有一个非常重要的子类:Vie ...
- Android视图控件架构分析之View、ViewGroup
在Android中,视图控件大致被分为两类,即ViewGroup和View,ViewGroup控件作为父控件,包含并管理着子View,通过ViewGroup和View便形成了控件树,各个ViewGou ...
随机推荐
- android httpUrlConnection HttpClient
韩梦飞沙 韩亚飞 313134555@qq.com yue31313 han_meng_fei_sha httpUrlConnection 超文本传输协议统一资源定位器连接 http 超 ...
- [Arc081F]Flip and Rectangles
[Arc081F]Flip and Rectangles 试题分析 首先考虑如何操作,发现我们只会选若干行和若干列来进行一次取反. 这个东西相当于什么呢?相当于交点不变,然后这些行和这些列的其它点取反 ...
- java设计模式(六)策略模式
适用于同一操作的不同行为,策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们可以相互替换,让算法独立于使用它的客户而独立变化,具体应用场景如第三方支付对接不同银行的算法. 要点:1)抽象策 ...
- java集合之一(框架介绍)
本文转载自:http://www.cnblogs.com/skywang12345/p/3308498.html Java集合主要可以划分为4个部分:List列表.Set集合.Map映射.工具类(It ...
- hdoj 5199 Gunner map
Gunner Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5199 D ...
- OPENCV----在APP性能测试中的应用(一)
应用项目: APP的性能测试 应用场景: APP启动速度 视频开播速度 加载速度 等~~ 缘来: 基于APP日志和UiAutomator的测试方案,测试结果不能直白且精确的反应,用户的体验 ...
- DEX 可视化查阅
参考: http://bbs.pediy.com/thread-208828.htm 010 Editor 下载地址: http://www.sweetscape.com/download/ //-- ...
- Linux 内核编译步骤及配置详解
前言 Linux内核是操作系统的核心,也是操作系统最基本的部分. Linux内核的体积结构是单内核的.但是他充分采用了微内核的设计思想.使得虽然是单内核.但工作在模块化的方式下.并且这个模块可以 ...
- Python如何import文件夹下的文件
Python的import包含文件功能就跟PHP的include类似,但更确切的说应该更像是PHP中的require,因为Python里的import只要目标不存在就报错程序无法往下执行.要包含目录里 ...
- panic: reflect.Value.Interface: cannot return value obtained from unexported field or method
go的结构体中私有的属性, 即使反射也获取不到