View.bringToFront()方法 ViewGroup.bringChildToFront(View child)将view显示在视图的最顶层

看项目时发现项目中有用到bringChildToFront(View child)方法,于是查了下相关资料,发现类似的方法在View类中也有对应的bringToFront()方法。

作用是一样的,都是将处在父控件中的某一子控件显示在父控件的最上层。具体的源码解析可参考一篇博文:

最近在项目终于到了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.Fragment和android.animation.LayoutTransition移除view的动画),还不能删除这个child,应该等到动画结束,所以在ViewGroup中暂时保留这个child,直到动画真正结束后再真正删除。ViewGroup有两个成对出现的方法:startViewTransition和endViewTransition。在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中删除。

作者的发现对不少人很有帮助,至于LayoutTransition我不是特别了解,放到以后再深入学习,这里先弄清bringToFront()方法。

其实View中的bringToFront()方法也是调用了父控件的bringChildToFront()方法实现的,View中具体代码如下:

/**
 * Change the view's z order in the tree, so it's on top of other sibling
 * views. This ordering change may affect layout, if the parent container
 * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
 * to {@link android.os.Build.VERSION_CODES#KITKAT} this
 * method should be followed by calls to {@link #requestLayout()} and
 * {@link View#invalidate()} on the view's parent to force the parent to redraw
 * with the new child ordering.
 *
 * @see ViewGroup#bringChildToFront(View)
 */
public void bringToFront() {
    if (mParent != null) {
        mParent.bringChildToFront(this);
    }
}
至此,大家应该对这两个方法有一定了解了,以后在项目开发中可以适当利用,实现一些控件控制操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值