您的位置:首页 > 移动开发 > Android开发

[置顶] Android ListView动画特效实现原理及源码

2014-07-04 20:01 495 查看
        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 

      多多提建议,多多交流~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: