1. 程式人生 > >Android ListView動畫特效實現原理及源代碼

Android ListView動畫特效實現原理及源代碼

stat 每一個 應該 所有 ner haar .get tde pri

Android 動畫分三種,當中屬性動畫為我們最經常使用動畫,且能滿足項目中開發差點兒所有需求,google官方包支持3.0+。我們能夠引用三方包nineoldandroids來失陪到低版本號。本樣例中就是用屬性動畫實現效果。

對普通的View做動畫,我們僅僅要定義好要的動畫ObjectAnimator或AnimatorSet。然後設置屬性啟動及可。

可是。對ListView做動畫應該怎樣、什麽時候、在什麽地方、對哪個View做動畫屬性呢?

github上有成熟的listview動畫包 https://github.com/nhaarman/ListViewAnimations.git , 基本能夠滿足比較炫的效果,比方google+動態list載入,各種動態list顯示及刪除。

問題是,假設不能滿足我們的需求,怎樣實現自己想要的ListView動畫效果呢?研究github上項目實現原理發現並不復雜。以下我們就參考開源項目實現自己的ListView動畫效果。

要想對ListView的Item做動畫,首先想到的是Adapter的getView()方法。在getView方面裏能夠獲得每一個Item view,然後定義好動畫效果,結合動畫需求對contentView做動畫。

如須要做一個刪除item時的動畫。能夠在getView時把View和position傳給做的動畫或動畫集,這個比較簡單見代碼:



public static AnimatorSet buildListRemoveAnimator(final View view, final List list,
            final MyAnimListAdapter adapter, final int index) {
        AnimatorListener al = new AnimatorListener() {

            @Override
            public void onAnimationStart(Animator animation) {
                // TODO Auto-generated method stub

            }

            @Override
            public void onAnimationRepeat(Animator animation) {
                // TODO Auto-generated method stub

            }

            @Override
            public void onAnimationEnd(Animator animation) {
                // TODO Auto-generated method stub
                list.remove(index);
                ViewHolder vh = (ViewHolder) view.getTag();
                vh.needInflate = true;

                adapter.notifyDataSetChanged();
            }

            @Override
            public void onAnimationCancel(Animator animation) {
                // TODO Auto-generated method stub

            }
        };

        AnimatorSet animatorSet = new AnimatorSet();
        Animator anim = ObjectAnimator.ofFloat(view, "rotationX", 0, 90);
        Animator animb = ObjectAnimator.ofFloat(view, "alpha", 1, 0);
        ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1);
        final int height = view.getMeasuredHeight();
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                // TODO Auto-generated method stub
                if (animation.getAnimatedFraction() >= 1) {
                    view.setVisibility(View.GONE);
                }
                else {
                    view.getLayoutParams().height = height
                            - (int) (height * animation.getAnimatedFraction());
                    view.requestLayout();
                }
            }
        });

        anim.setDuration(ANIMATION_DURATION);
        animb.setDuration(ANIMATION_DURATION);
        valueAnimator.setDuration(ANIMATION_DURATION + ANIMATION_DURATION + 100);
        animatorSet.playTogether(anim, animb, valueAnimator);
        animatorSet.addListener(al);
        return animatorSet;
    }


怎樣做一個listview動態現實每一個Item的顯示效果。這個教刪除復雜,須要計算每一個item動畫的開始時間,及推斷是否動畫現實。還有就是顯示動畫要依照什麽樣的規則或是順序, 計算動畫現實的時間等因素。而且不好優化list的性能,及顯示效果。

以下的樣例僅僅是實現了基本動畫效果。性能優化欠缺。


public static AnimatorSet buildShowAnimatorList(ViewGroup parent, ListView list, View view, long mAnimationStartMillis,
            int mLastAnimatedPosition, int mFirstAnimatedPosition) {
        if (mAnimationStartMillis == -1) {
            mAnimationStartMillis = System.currentTimeMillis();
        }
        ViewHelper.setAlpha(view, 0);
        Animator alphaAnimator = ObjectAnimator.ofFloat(view, "alpha", 0, 1);
        Animator rx = ObjectAnimator.ofFloat(view, "rotationX", -90, 0);
        AnimatorSet set = new AnimatorSet();
        set.playTogether(alphaAnimator, rx);
        set.setStartDelay(calculateAnimationDelay(list, mLastAnimatedPosition, mFirstAnimatedPosition,mAnimationStartMillis));
        set.setDuration(DEFAULTANIMATIONDELAYMILLIS);
        set.start();
        return set;
    }

    private static long calculateAnimationDelay(ListView list, int last, int first,long starmill) {
        long delay;

        int lastVisiblePosition = list.getLastVisiblePosition();
        int firstVisiblePosition = list.getFirstVisiblePosition();

        int numberOfItemsOnScreen = lastVisiblePosition - firstVisiblePosition;
        int numberOfAnimatedItems = last - first;

        if (numberOfItemsOnScreen + 1 < numberOfAnimatedItems) {
            delay = DEFAULTANIMATIONDELAYMILLIS;

        } else {
            long delaySinceStart = (last - first + 1)
                    * DEFAULTANIMATIONDELAYMILLIS;
            delay = starmill + DEFAULTANIMATIONDELAYMILLIS + delaySinceStart
                    - System.currentTimeMillis();
        }
        return Math.max(0, delay);
    }


參照上面的方法能夠實現自己想要的ListView Item動畫,而且能夠去自己定義想要的效果。

本例源代碼地址:

https://github.com/CankingApp/ListAnimator

多多提建議。多多交流~

Android ListView動畫特效實現原理及源代碼