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 ...
随机推荐
- BZOJ 1174 [Balkan2007]Toponyms(Trie)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1174 [题目大意] 选出一些字符串,使得字符串的最长公共前缀*字符串的总个数最大化 [ ...
- 我们为什么需要Map-Reduce?
在讨论我们是否真的需要Map-Reduce这一分布式计算技术之前,我们先面对一个问题,这可以为我们讨论这个问题提供一个直观的背景. 问题 我们先从最直接和直观的方式出发,来尝试解决这个问题: 先伪一下 ...
- 开发npm模块经验总结
1.在windows下开发的package.json的bin链接的全局命令可能会在linux下报错:“没有那个文件或目录”之类的错误...此时可以在linux下用vim打开bin链接的js文件,设置s ...
- Run native executable in Android App
Run native executable in Android App Demo † Here's demo application called "Run Native Exe" ...
- Towelroot v3.0版发布 将支持更多设备 Towelroot v3.0下载
Towelroot虽然已经发布一段时间了,虽然所Towelroot可以一键ROOT很多设备,虽然它只有100多K.不过还是有一小部分的机型没办法ROOT成功的,也不知道什么原因.不过不用担心,Geoh ...
- My安装EclipseJS代码提示(Spket插件)
最近须要大量使用JS来开发,可是MyEclipse2014自带的JS编辑器没有代码提示的功能,开发效率有点低,所以安装了一个Spket的插件,过程很easy,SVN插件的安装比这个更简单. Spket ...
- C#程序集系列01,用记事本编写C#,IL代码,用DOS命令编译程序集,运行程序
本篇主要体验:编写C#,IL代码,用"VS2012开发人员命令提示"编译成程序集,并运行程序. □ C#文件编译为程序集 →在F盘创建as文件夹→在as文件夹下创建MyClass. ...
- 游戏编程之Unity常用脚本类的继承关系
前言学习Unity开发引擎的初学者会接触大量的脚本类,而这些类之间的关系往往容易被忽略.本文对Unity引擎开发中的一些常用类及其关系进行了简单的归纳总结. 博文首发地址:http://tieba.b ...
- 【docker】docker基础原理,核心技术简介
关于docker的核心技术,就是以下的三大技术: 1.namespaces [命名空间] 使用linux的命名空间实现的进程间隔离.Docker 容器内部的任意进程都对宿主机器的进程一无所知. 除了进 ...
- .Net异步编程 z
1. 引言 最近在学习Abp框架,发现Abp框架的很多Api都提供了同步异步两种写法.异步编程说起来,大家可能都会说异步编程性能好.但好在哪里,引入了什么问题,以及如何使用,想必也未必能答的上来. 自 ...