前段时间在项目中遇见偶现setVisibility(View.GONE) 和 removeView(view)失效问题,通过各种追踪分析最后发现是由于 View 在执行动画过程中调用 setVisibility或 removeView 失效导致的。
在动画过程中setVisibility(View.GONE) 失效原因分析
在 ViewGroup 中的 dispatchDraw 函数中有以下代码:
image.png
通过以上代码可知当 View 存在执行的动画时则忽略了 View.GONE 属性会继续绘制出现。
解决方案是:
在执行动画的 View调用 setVisibility前先调用 clearAnimation;
在动画执行完后也调用clearAnimation,防止出现 setVisibility 失效问题出现。
在动画过程中removeView(View view) 失效原因分析
源码分析:
public void removeView(View view) {
if (removeViewInternal(view)) {
requestLayout();
invalidate(true);
}
}
在removeView中调用removeViewInternal(view)再走到removeViewInternal(int index, View view),其里面的代码比较多不全部贴出,里面关键代码
image.png
红框中显示如果当前 view 存在动画则会走到addDisappearingView函数,其代码
/**
* Add a view which is removed from mChildren but still needs animation
*
* @param v View to add
*/
private void addDisappearingView(View v) {
ArrayList<View> disappearingChildren = mDisappearingChildren;
if (disappearingChildren == null) {
disappearingChildren = mDisappearingChildren = new ArrayList<View>();
}
disappearingChildren.add(v);
}
通过注释和代码知道是把当前的 view 放到mDisappearingChildren列表中,这个列表里面存放的是存在动画的待移出的 view
在 ViewGroup 中的 dispatchDraw(Canvas canvas)函数中发现用到了 mDisappearingChildren这个列表
image.png
通过注释和代码显示这些待消失的view会继续被绘制
总结分析:执行动画过程中的 view 如果 被 remove 掉还是会被绘制,只是系统为了保证动画的完整性
解决方案:在remove掉存在动画的 view 之前先 clearAnimation
个人思考:
android系统为了保证 View动画的完整性,在 View 执行动画过程中不会把 View GONE 或 remove 掉。









网友评论