Animation導致removeView無效(源碼分析)

繼續入自定義View的坑,最近實現一個效果的時候,需要動態添加和刪除View,所以就要用到ViewGroup中的removeView和addView,按理來說應該很簡單,但是我遇到了一個問題,發現removeView無效。
最后發現:當你要remove的View正在執行Animation效果的時候,是無法remove掉的,所以需要先clearAnimation,再remove

從源碼中證實了我的觀點:

    public void removeViewAt(int index) {
        removeViewInternal(index, getChildAt(index));
        requestLayout();
        invalidate(true);
    }

我調用的是removeViewAt方法,可以看到,實際上起作用的是removeViewInternal方法

private void removeViewInternal(int index, View view) {
        ...

        if (view.getAnimation() != null || (mTransitioningViews != null 
                        &&mTransitioningViews.contains(view))) {
            addDisappearingView(view);
        } else if (view.mAttachInfo != null) {
           view.dispatchDetachedFromWindow();
        }   
        ...
    }

一樣,當我第一樣看到這個方法,我是拒絕的,很長的方法體,非常多的變量不知道含義,第一次看我沒有找到原因。第二次再看的時候,我發現了上面這段代碼,非常符合我要尋找的問題,當View的Animation不是null的時候,會執行addDisappearingView(view)

    /**
     * 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);
    }

可以看到,Google的解釋其實已經很清楚了,添加一個帶有動畫效果的View。
我看到這還是有點不確定,這里面沒有真正意義上的將Remove的View重繪到組件上。
所以我查詢了mDisappearingChildren這個對象,看在哪里使用了這個對象

@Override
    protected void dispatchDraw(Canvas canvas) {
        ...

        // Draw any disappearing views that have animations
        if (mDisappearingChildren != null) {
            final ArrayList<View> disappearingChildren = mDisappearingChildren;
            final int disappearingCount = disappearingChildren.size() - 1;
            // Go backwards -- we may delete as animations finish
            for (int i = disappearingCount; i >= 0; i--) {
                final View child = disappearingChildren.get(i);
                more |= drawChild(canvas, child, drawingTime);
            }
        }
        ...
    }

可以看到,我在dispatchDraw方法中找到了我想要的結果,可以看到,注釋寫的也很清楚,在重繪的時候,會將仍然有Animation的View繪制出來。
可以看到,這里遍歷了mDisappearingChildren,調用了drawChild進行繪制。

到此問題解決,小小的看了一下源碼,也是很有趣的

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容