bringToFront 的意外发现

作者: joshualiyz | 来源:发表于2016-06-16 20:22 被阅读392次

原文地址在博客圆,已经不用了,迁移过来。

最近在项目用到了View.bringToFront()方法,简单看了下其源码,在这儿总结一下。

bringToFront方法在SDK中的说明是“Change the view's z order in the tree, so it's on top of other sibling views”,翻译过来就是改变view的z轴,使其处在他父view的顶端。关于bringToFront的实现,网上有很多资料介绍,大体来说就是将这个view从父view中移除,然后再加入父view的顶端。具体实现如何呢?

bringToFront的具体实现要参看ViewGroup中的bringChildToFront方法。代码很简单,如下:

public void bringChildToFront(View child) {
        int index = indexOfChild(child);
        if (index >= 0) {
            removeFromArray(index);
            addInArray(child, mChildrenCount);
            child.mParent = this;
        }
    }

分两步,首先remove,然后add,实际上ViewGroup维持了一个View数组,addInArray方法会把这个child加入到数组最末端,在draw的时候,将依次画数组中的child,最后一个自然就放到了顶端。
removeFromArray方法中有一段奇怪的代码:

if (!(mTransitioningViews != null && mTransitioningViews.contains(children[index]))) {
            children[index].mParent = null;
}

mTransitioningViews官方解释如下:

The set of views that are currently being transitioned. This list is used to track views being removed that should not actually be removed from the parent yet because they are being animated.

正如上述,当某个child正在做动画的时候(这里指android.app.Fragmentandroid.animation.LayoutTransition移除view的动画),还不能删除这个child,应该等到动画结束,所以在ViewGroup中暂时保留这个child,直到动画真正结束后再真正删除。ViewGroup有两个成对出现的方法:startViewTransitionendViewTransition。在startViewTransition方法中将child加入mTransitioningViews中,在endViewTransition中最终执行view.dispatchDetachedFromWindow(),并在函数最后调用invalidate()

值得一提的是,在removeView的时候,如果当前child在mTransitioningViews中,ViewGroup并不会执行view.dispatchDetachedFromWindow(),也不会设置当前view的mParent为空。

没想到分析bringToFront方法竟然还意外发现一个mTransitioningViews,由此可以看到一个潜在的问题,如果我们在执行LayoutTransition的DISAPPEARING动画同时removeView,这时子view还并未删除,如果直接将子view加入其它ViewGroup中则会报错“The specified child already has a parent. You must call removeView() on the child's parent first.” 因为此时这个view还未从上一个ViewGroup中删除。

相关文章

  • bringToFront 的意外发现

    原文地址在博客圆,已经不用了,迁移过来。 最近在项目用到了View.bringToFront()方法,简单看了下其...

  • bringToFront的意外发现

    最近在项目终于到了View.bringToFront()方法,简单看了下其源码,在这儿总结一下。 bringToF...

  • 布局的bringToFront方法

    bringToFront这是我今天的意外发现在我刚代码的时候发现的所以赶紧去百度了一波bringToFront方法...

  • Android View中bringToFront()

    1、bringToFront(): 最近在项目终于到了View.bringToFront()方法,简单看了下其源码...

  • 意外的发现

    这几天一直在临《宣示表》,每次新笔用过后清理的很干净,笔锋保存的也很好,但是第二次再用,笔锋却莫名其妙的没了,甚是...

  • 意外的发现

    今天上午给客人做完艾灸,将客人送走后,我回到了禅房,只有我自己,然后看了一会儿书,拿水杯去倒点水喝,走到前台时,看...

  • 意外的发现

  • 意外的发现

    男人是三年前下岗的,左思右想后决定开一家水果店。 对于他的想法,女人向来支持。她身体弱,进医院是家常便饭,所...

  • 意外的发现

    自从在简书上记录柴米油盐事,以上截图内容还是头一回发现。有白茫茫大地真干净的感觉。 昨天上午去单位的时候,零零星星...

  • 意外的发现

    在两栋单元楼正后方,遗留了一小批老革命建筑,被遗弃荒废,斑驳的墙壁与朽败的木梁透露出漫长岁月的浸润。 这里十分安静...

网友评论

本文标题:bringToFront 的意外发现

本文链接:https://www.haomeiwen.com/subject/iunmdttx.html