Canvaseventloopgroup 作用有什么作用

下次自动登录
现在的位置:
深入理解Android中ViewGroup
文章目录[]
& & & & & & 这回我们是深入到ViewGroup内部\,了解ViewGroup的工作,同时会阐述更多有关于View的相关知识。以便为以后能灵活的使用自定义空间打更近一步的基础。希望有志同道合的朋友一起来探讨,深入Android内部,深入理解Android。
一、ViewGroup是什么?
& & & &一个ViewGroup是一个可以包含子View的容器,是布局文件和View容器的基类。在这个类里定义了ViewGroup.LayoutParams类,这个类是布局参数的子类。
& & & &其实ViewGroup也就是View的容器。通过ViewGroup.LayoutParams来指定子View的参数。
ViewGroup作为一个容器,为了制定这个容器应有的标准所以为其指定了接口
public abstract class ViewGroup extends View implements ViewParent, ViewManager
& & & &这两个接口这里不研究,如果涉及到的话会带一下。ViewGroup有小4000行代码,下面我们一个模块一个模块分析。
二、ViewGroup这个容器
& & & &ViewGroup是一个容器,其采用一个数组来存储这些子View:
// Child views of this ViewGroup
private View[] mC
& & & &由于是通过一个数组来存储View数据的,所以对于ViewGroup来说其必须实现增、删、查的算法。下面我们就来看看其内部实现。
2.1 添加View的算法
protected boolean addViewInLayout(View child, int index, LayoutParams params) {
return addViewInLayout(child, index, params, false);
protected boolean addViewInLayout(View child, int index, LayoutParams params,
boolean preventRequestLayout) {
child.mParent =
addViewInner(child, index, params, preventRequestLayout);
child.mPrivateFlags = (child.mPrivateFlags & ~DIRTY_MASK) | DRAWN;
private void addViewInner(View child, int index, LayoutParams params,
boolean preventRequestLayout) {
addInArray(child, index);
private void addInArray(View child, int index) {
& & & &上面四个方法就是添加View的核心算法的封装,它们是层层调用的关系。而我们通常调用的addView就是最终通过上面那个来最终达到添加到ViewGroup中的。
& &2.1.1 我们先来分析addViewInner方法:
首先是对子View是否已经包含到一个父容器中,主要的防止添加一个已经有父容器的View,因为添加一个拥有父容器的View时会碰到各种问题。比如记录本身父容器算法的问题、本身被多个父容器包含时更新的处理等等一系列的问题都会出现。
if (child.getParent() != null) {
throw new IllegalStateException("The specified child already has a parent. " +
"You must call removeView() on the child's parent first.");
然后就是对子View布局参数的处理。
调用addInArray来添加View
父View为当前的ViewGroup
焦点的处理。
当前View的AttachInfo信息,这个信息是用来在窗口处理中用的。Android的窗口系统就是用过AttachInfo来判断View的所属窗口的,这个了解下就行。详细信息设计到Android框架层的一些东西。
AttachInfo ai = mAttachI
if (ai != null) {
boolean lastKeepOn = ai.mKeepScreenOn;
ai.mKeepScreenOn =
child.dispatchAttachedToWindow(mAttachInfo, (mViewFlags&VISIBILITY_MASK));
if (ai.mKeepScreenOn) {
needGlobalAttributesUpdate(true);
ai.mKeepScreenOn = lastKeepOn;
View树改变的监听
if (mOnHierarchyChangeListener != null) {
mOnHierarchyChangeListener.onChildViewAdded(this, child);
子View中的mViewFlags的设置:
if ((child.mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE) {
mGroupFlags |= FLAG_NOTIFY_CHILDREN_ON_DRAWABLE_STATE_CHANGE;
2.1.2 addInArray
& & & &这个里面的实现主要是有个知识点,以前也没用过arraycopy,这里具体实现就不多加描述了。
System.arraycopy(children, 0, mChildren, 0, index);
System.arraycopy(children, index, mChildren, index + 1, count - index);
2.2 移除View
& & & &移除View的几种方式:
移除指定的View。
移除从指定位置的View
移除从指定位置开始的多个View
移除所有的View
& & & &其中具体涉及到的方法就有好多了,不过最终对要删除的子View中所做的无非就是下列的事情:
如果拥有焦点则清楚焦点
将要删除的View从当前的window中解除关系。
设置View树改变的事件监听,我们可以通过监听OnHierarchyChangeListener事件来进行一些相应的处理。
从父容器的子容器数组中删除。
& & & &具体的内容这里就不一一贴出来了,大家回头看看源码就哦了。
& & & &这个就简单了,就是直接从数组中取出就可以了:
public View getChildAt(int index) {
return mChildren[index];
} catch (IndexOutOfBoundsException ex) {
& & & &分析到这儿,其实我们已经相当于分析了ViewGroup四分之一的代码了,呵呵。
三、onFinishInflate
& & & &我们一般使用View的流程是在onCreate中使用setContentView来设置要显示Layout文件或直接创建一个View,在当设置了ContentView之后系统会对这个View进行解析,然后回调当前视图View中的onFinishInflate方法。只有解析了这个View我们才能在这个View容器中获取到拥有Id的组件,同样因为系统解析完View之后才会调用onFinishInflate方法,所以我们自定义组件时可以onFinishInflate方法中获取指定子View的引用。
四、测量组件
& & & &在ViewGroup中提供了测量子组件的三个方法。
//1、measureChild(View, int, int),为子组件添加Padding
protected void measureChild(View child, int parentWidthMeasureSpec,
int parentHeightMeasureSpec) {
final LayoutParams lp = child.getLayoutParams();
final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec,
mPaddingLeft + mPaddingRight, lp.width);
final int childHeightMeasureSpec = getChildMeasureSpec(parentHeightMeasureSpec,
mPaddingTop + mPaddingBottom, lp.height);
child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
//2、measureChildren(int, int)根据指定的高和宽来测量所有子View中显示参数非GONE的组件。
protected void measureChildren(int widthMeasureSpec, int heightMeasureSpec) {
final int size = mChildrenC
final View[] children = mC
for (int i = 0; i & ++i) {
final View child = children[i];
if ((child.mViewFlags & VISIBILITY_MASK) != GONE) {
measureChild(child, widthMeasureSpec, heightMeasureSpec);
3、measureChildWithMargins(View, int, int, int, int)测量指定的子组件,为子组件添加Padding和Margin。
protected void measureChildWithMargins(View child,
int parentWidthMeasureSpec, int widthUsed,
int parentHeightMeasureSpec, int heightUsed) {
final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec,
mPaddingLeft + mPaddingRight + lp.leftMargin + lp.rightMargin
+ widthUsed, lp.width);
final int childHeightMeasureSpec = getChildMeasureSpec(parentHeightMeasureSpec,
mPaddingTop + mPaddingBottom + lp.topMargin + lp.bottomMargin
+ heightUsed, lp.height);
child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
& & & &上面三个方法都是为子组件设置了布局参数。最终调用的方法是子组件的measure方法。在View中我们知道这个调用实际上就是设置了子组件的布局参数并且调用onMeasure方法,最终设置了View测量后的高度和宽度。
五、onLayout
& & & &这个函数是一个抽象函数,要求实现ViewGroup的函数必须实现这个函数,这也就是ViewGroup是一个抽象函数的原因。因为各种组件实现的布局方式不一样,而onLayout是必须被重载的函数。
protected abstract void onLayout(boolean changed,
int l, int t, int r, int b);
我们回头来看View中layout方法:
public final void layout(int l, int t, int r, int b) {
boolean changed = setFrame(l, t, r, b);
if (changed || (mPrivateFlags & LAYOUT_REQUIRED) == LAYOUT_REQUIRED) {
if (ViewDebug.TRACE_HIERARCHY) {
ViewDebug.trace(this, ViewDebug.HierarchyTraceType.ON_LAYOUT);
onLayout(changed, l, t, r, b);
mPrivateFlags &= ~LAYOUT_REQUIRED;
mPrivateFlags &= ~FORCE_LAYOUT;
& & & &在这个方法中调用了setFrame方法,这个方法是用来设置View中的上下左右边距用的
protected boolean setFrame(int left, int top, int right, int bottom) {
boolean changed =
if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
// Remember our drawn bit
int drawn = mPrivateFlags & DRAWN;
// Invalidate our old position
invalidate();
int oldWidth = mRight - mL
int oldHeight = mBottom - mT
mPrivateFlags |= HAS_BOUNDS;
int newWidth = right -
int newHeight = bottom -
if (newWidth != oldWidth || newHeight != oldHeight) {
onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
if ((mViewFlags & VISIBILITY_MASK) == VISIBLE) {
// If we are visible, force the DRAWN bit to on so that
// this invalidate will go through (at least to our parent).
// This is because someone may have invalidated this view
// before this call to setFrame came in, therby clearing
// the DRAWN bit.
mPrivateFlags |= DRAWN;
invalidate();
// Reset drawn bit to original value (invalidate turns it off)
mPrivateFlags |=
mBackgroundSizeChanged =
//我们可以看到如果新的高度和宽度改变之后会调用重新设置View的四个参数:
//protected int mL
//protected int mR
//protected int mT
//protected int mB
//这四个参数指定了View将要布局的位置。而绘制的时候是通过这四个参数来绘制,所以我们在View中调用layout方法可以实现指定子View中布局。
六、ViewGroup的绘制。
& & & &ViewGroup的绘制实际上是调用的dispatchDraw,绘制时需要考虑动画问题,而动画的实现实际上就通过dispatchDraw来实现的。
& & & &我们不用理会太多的细节,直接看其绘制子组件调用的是drawChild方法,这个里面具体的东西就多了,涉及到动画效果的处理,如果有机会的话再写,我们只要知道这个方法的功能就行。
这里有个demo贴出其中的代码大家可以测试下。
public ViewGroup01(Context context)
super(context);
Button mButton = new Button(context);
mButton.setText("测试");
addView(mButton);
protected void onLayout(boolean changed, int l, int t, int r, int b)
View v = getChildAt(0);
if(v != null)
v.layout(120, 120, 250, 250);
protected void dispatchDraw(Canvas canvas)
super.dispatchDraw(canvas);
View v = getChildAt(0);
if(v != null)
drawChild(canvas, v, getDrawingTime());
七、效果图片:
【上篇】【下篇】
您可能还会对这些文章感兴趣!
您必须才能发表留言!
&&支持公益事业,您可以访问本站的,多一份关怀,多一份关爱
&&当然如果您想为本站做点什么,可以帮忙轻点页面底部的广告。
仿照小米层叠翻页效果,主要是使用ViewGroup来实现
jbox2d基于Android开发,box2d,在Android上使用box2d,这里提供了测试的debugView,可以很方便的实现绘制和数据逻辑的分离,并且提供源码下载
Android开发思想,以及Android开发中碰到的问题,Andorid上面的一些解决方案,UGUI多个Canvas的渲染先后层次关系设置 - -
【狗刨学习网】-Unity3D培训&学习社区 - |Unity3D培训|北京Unity培训|Unity企业培训|Unity程序员培训|Unity学习|Unity自学|Unity视频教程|Unity教程|Unity就业班
发表于 06-07
1358 次查看
欢迎来到、、教育专区,这里有很多、、、、,【狗刨学习网】,致力于打造业内、学习第一品牌。
这几天在做游戏的WindowManager,一开始只是想到打开单一窗口和设置窗口并存的问题,一切运行良好。
但是昨天加了一个等待窗口(沙漏加菊花)之后就出现了问题。
首先说明我的Window的结构:一个空的GameObject
所有的UI控件
举例说:在登录界面,,点击登录按钮后向服务器发送登录请求,这个时候会显示转菊花的界面,一切OK。
窗口打开顺序为 登录窗口
--- 等待窗口
下面的大图就是登录窗口,上面的就是沙漏菊花等待窗口。
这个时候如果再弹出一个其它的界面,比如弹出了一个滚动公告,那按照先后顺序来说,滚动公告就会显示在等待界面之上,这是不行的。
我的目的呢,就是要让等待界面显示在最上面!
首先,从MOMO的博文中了解到,貌似有一个API可以使用,
SetSiblingIndex
就是设置 物体在视图中的顺序。
但是实际使用后得出结论,这个API只能调整在同一个Canvas下的UI控件的渲染顺序。对于多个Canvas的不同的窗口而言,这个API没有用处。
于是百度谷歌之,得到一些苗头:
Unity3d中的渲染顺序如下:
不同Camera的Depth
同Camera的soringLayer
同sortingLayer下面的Z轴
但是没有适合我的。
正准备把所有的窗口都由Canvas来管理的时候,看到Canvas下面有一个Sort Order 。
Sort这个词看起来就比较符合口味,排序嘛!
试着把菊花窗口的Sort修改为100,再运行,果然生效!
测试:先打开等待界面,然后打开登录界面,不设置Sort Order:
可以看到菊花界面无情的被其它界面遮挡住了。
然后先打开等待界面,再打开其它界面,设置等待界面Canvas的Sort Order为100(因为默认是0,这里可以设置为无限大)
这下就OK了,等待界面永远在其它界面之上了,除非你把其它界面的Sort Order设置的比等待界面大.
更多内容,请访问
你还没有登录,请先或!
头衔:游戏主程请教一下 View中的draw和onDraw有什么区别_百度知道
请教一下 View中的draw和onDraw有什么区别
  绘制VIew本身的内容,通过调用View.onDraw(canvas)函数实现  绘制自己的孩子通过dispatchDraw(canvas)实现  View组件的绘制会调用draw(Canvas canvas)方法,draw过程中主要是先画Drawable背景,对 drawable调用setBounds()然后是draw(Canvas c)方法.有点注意的是背景drawable的实际大小会影响view组件的大小,drawable的实际大小通过getIntrinsicWidth()和getIntrinsicHeight()获取,当背景比较大时view组件大小等于背景drawable的大小。
画完背景后,draw过程会调用onDraw(Canvas canvas)方法,然后就是dispatchDraw(Canvas canvas)方法, dispatchDraw()主要是分发给子组件进行绘制,我们通常定制组件的时候重写的是onDraw()方法。值得注意的是ViewGroup容器组件的绘制,当它没有背景时直接调用的是dispatchDraw()方法, 而绕过了draw()方法,当它有背景的时候就调用draw()方法,而draw()方法里包含了dispatchDraw()方法的调用。因此要在ViewGroup上绘制东西的时候往往重写的是dispatchDraw()方法而不是onDraw()方法,或者自定制一个Drawable,重写它的draw(Canvas c)和 getIntrinsicWidth(),getIntrinsicHeight()方法,然后设为背景。
其他类似问题
为您推荐:
提问者采纳
了楼上几位的讨论,我的理解是我们在自定义view的时候只需要重写onDraw();&gt,因为onDraw()是draw()方法的一部分。
查看原帖&gt,而没必要去重写draw()
提问者评价
其他1条回答
If necessary。也就是draw会调用onDraw,不过Android官方推荐用只用onDraw就可以了, you should implement onDraw”
查看原帖& instead, do not override this method,draw()这个函数本身会做很多事情,一般情况下,可以调用draw(); layers to prepare for fading * 3. Draw the background * 2. Is content * 4,来绘制view的内容, * 1。“When implementing a view,如果绘制多一点的内容, draw the fading edges and restore layers * 6. Draw decorations (scrollbars for instance)在第三步的时候,直接用onDraw绘制view的content就可以了, save the canvas&#39。所以看需要;&gt. Draw children * 5. Draw view&#39大概扫一下源码就可以明白,它就会调用onDraw()方法
ondraw的相关知识
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁Canvas Church - Deepen Your Faith, Find Your Place, Discover Your Purpose, Make a Difference
DEEPEN YOUR FAITH
FIND YOUR PLACE
DISCOVER YOUR PURPOSE
MAKE A DIFFERENCE
Sundays @ 9:30 & 11:00 | Northfield High School 1400 Division Street South Northfield, MN 55057 | Click for MAP
Welcome to Canvas Church! At Canvas, it is our passion to see people find their place, deepen their faith, and make a difference. Jesus wants to meet you wherever you are to show you how much He loves you and the amazing plan He has for your life. So, we invite you to open your heart to what He has for you today.
– Jeff & Tiffany Wendt
HAPPENING THIS WEEK…
21 Days of Prayer and Fasting
Group: Our ChurchCampus: Canvas Church-Northfield
24/7 Prayer
Group: Our Church
Campus: Canvas Church-Northfield
Center Vine Youth Group
Life 21 Church
Group: Center Student Ministries
Campus: Canvas Church-Northfield
A time for students to connect with each other and learn about God.
Youth Mexico Trip Info Meeting
Life 21 Church
CURRENT SERMON SERIES
We believe God’s Word is powerful and life-changing. Catch up on our current sermon series, Life on Purpose, by listening to our most recent messages.
Check out the latest
on Check out the latest
on Check out the latest
on Check out the latest
on Check out the latest

我要回帖

更多关于 canvas group 的文章

 

随机推荐