1 概念
ListViewAnimations是一个带Item显示动画的ListView,动画包括底部飞入、其他方向斜飞入、下层飞入、渐变消失、滑动删除等
Demo地址:https://play.google.com/store/apps/details?id=com.haarman.listviewanimations
- lib-core:这是ListViewAnimations的核心库,它包含各种各样的动画效果
- lib-manipulation:包括一些对listView item的操作,例如 Swipe-to-Dismiss, and Drag-and-Drop
- lib-core=slh:对核心库库进行了扩展,支持StickyListHeaders(轻松给listView添加header)
(2) build.gradle配置
repositories {
mavenCentral()
}
dependencies {
compile 'com.nhaarman.listviewanimations:lib-core:3.1.0@aar'
compile 'com.nhaarman.listviewanimations:lib-manipulation:3.1.0@aar'
compile 'com.nhaarman.listviewanimations:lib-core-slh:3.1.0@aar'
}
3 如何移植项目
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_appearanceexample);
mListView = (ListView) findViewById(R.id.activity_appearanceexample_listview);
mCurrentListView = mListView;
mAdapter = new MyAdapter(this, getItems());
setRightAdapter();
}
private void setRightAdapter() {
AnimationAdapter animAdapter = new SwingRightInAnimationAdapter(mAdapter);
animAdapter.setAbsListView(mCurrentListView);
mCurrentListView.setAdapter(animAdapter);
}
protected final BaseAdapter mDecoratedBaseAdapter;
private AbsListView mListView;
public BaseAdapterDecorator(BaseAdapter baseAdapter) {
mDecoratedBaseAdapter = baseAdapter;
}
public void setAbsListView(AbsListView listView) {
mListView = listView;
if (mDecoratedBaseAdapter instanceof BaseAdapterDecorator) {
((BaseAdapterDecorator) mDecoratedBaseAdapter).setAbsListView(listView);
}
if (mListView instanceof DynamicListView) {
DynamicListView dynListView = (DynamicListView) mListView;
dynListView.setIsParentHorizontalScrollContainer(mIsParentHorizontalScrollContainer);
dynListView.setDynamicTouchChild(mResIdTouchChild);
}
}
public class SwingRightInAnimationAdapter extends SingleAnimationAdapter {
private final long mAnimationDelayMillis;
private final long mAnimationDurationMillis;
public SwingRightInAnimationAdapter(BaseAdapter baseAdapter) {
this(baseAdapter, DEFAULTANIMATIONDELAYMILLIS, DEFAULTANIMATIONDURATIONMILLIS);
}
public SwingRightInAnimationAdapter(BaseAdapter baseAdapter, long animationDelayMillis) {
this(baseAdapter, animationDelayMillis, DEFAULTANIMATIONDURATIONMILLIS);
}
public SwingRightInAnimationAdapter(BaseAdapter baseAdapter, long animationDelayMillis, long animationDurationMillis) {
super(baseAdapter);
mAnimationDelayMillis = animationDelayMillis;
mAnimationDurationMillis = animationDurationMillis;
}
@Override
protected long getAnimationDelayMillis() {
return mAnimationDelayMillis;
}
@Override
protected long getAnimationDurationMillis() {
return mAnimationDurationMillis;
}
@Override
protected Animator getAnimator(ViewGroup parent, View view) {
return ObjectAnimator.ofFloat(view, "translationX", parent.getWidth(), 0);
}
}
4.3 AnimationAdapter源码
AnimationAdapter是BaseAdapterDecorator的子类,在4.1中我们已经知道了,BaseAdapterDecorator中有getView,getItem这些类似于adapter的方法其实就是我们自己定义的ListView的适配器中的方法.
@Override
public int getCount() {
return mDecoratedBaseAdapter.getCount();
}
@Override
public Object getItem(int position) {
return mDecoratedBaseAdapter.getItem(position);
}
@Override
public long getItemId(int position) {
return mDecoratedBaseAdapter.getItemId(position);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
return mDecoratedBaseAdapter.getView(position, convertView, parent);
}
@Override
public final View getView(int position, View convertView, ViewGroup parent) {
boolean alreadyStarted = false;
if (!mHasParentAnimationAdapter) {
if (getAbsListView() == null) {
throw new IllegalStateException("Call setListView() on this AnimationAdapter before setAdapter()!");
}
if (convertView != null) {
alreadyStarted = cancelExistingAnimation(position, convertView);
}
}
View itemView = super.getView(position, convertView, parent);
if (!mHasParentAnimationAdapter && !alreadyStarted) {
animateViewIfNecessary(position, itemView, parent);
}
return itemView;
}
private void hideView(View view) {
ObjectAnimator animator = ObjectAnimator.ofFloat(view, "alpha", 0);
AnimatorSet set = new AnimatorSet();
set.play(animator);
set.setDuration(0);
set.start();
}
@Override
protected Animator getAnimator(ViewGroup parent, View view) {
return ObjectAnimator.ofFloat(view, "translationX", parent.getWidth(), 0);
}
set.setStartDelay(calculateAnimationDelay(isHeader));
@SuppressLint("NewApi")
private long calculateAnimationDelay(boolean isHeader) {
long delay;
int numberOfItems = getAbsListView().getLastVisiblePosition() - getAbsListView().getFirstVisiblePosition();
if (numberOfItems + 1 < mLastAnimatedPosition) {
delay = getAnimationDelayMillis();
if (getAbsListView() instanceof GridView && Build.VERSION.SDK_INT >= 11) {
delay += getAnimationDelayMillis() * ((mLastAnimatedPosition + 1) % ((GridView) getAbsListView()).getNumColumns());
}
} else {
long delaySinceStart = (mLastAnimatedPosition - mFirstAnimatedPosition + 1) * getAnimationDelayMillis();
delay = mAnimationStartMillis + getInitialDelayMillis() + delaySinceStart - System.currentTimeMillis();
delay -= isHeader && mLastAnimatedPosition > 0 ? getAnimationDelayMillis() : 0;
}
// System.out.println(isHeader + ": " + delay);
return Math.max(0, delay);
}
Animator[] animators = getAnimators(parent, view);
Animator alphaAnimator = ObjectAnimator.ofFloat(view, "alpha", 0, 1);
AnimatorSet set = new AnimatorSet();
set.playTogether(concatAnimators(childAnimators, animators, alphaAnimator));
set.setStartDelay(calculateAnimationDelay(isHeader));
set.setDuration(getAnimationDurationMillis());
set.start();
源码就这么简单,原理就是当adapter再调用getView的时候,给每个item一个动画效果。
public interface IAnimationManager {
public void startRightAppearanceAnimation(int position,View view, ViewGroup parent);
}
5.2 新建一个类实现IAnimationManager接口
public class AnimationModel implements IAnimationManager {
private boolean ifCanAnimation;//是否启动动画,true运行动画,false动画停止
/**
* listView item从右边出现动画效果
*/
@Override
public void startRightAppearanceAnimation(int position,View view, ViewGroup parent) {
if(!ifCanAnimation) return;
//隐藏itemView
ObjectAnimator animator = ObjectAnimator.ofFloat(view, "alpha", 0);
AnimatorSet hiddenSet = new AnimatorSet();
hiddenSet.play(animator);
hiddenSet.setDuration(0);
hiddenSet.start();
//item从右出现动画
view.measure(0,0);
ObjectAnimator oa = ObjectAnimator.ofFloat(view, "translationX", view.getMeasuredWidth(), 0);
Animator alphaAnimator = ObjectAnimator.ofFloat(view, "alpha", 0, 1);
AnimatorSet set = new AnimatorSet();
long delay = 100 * (position-1);
set.playTogether(oa,alphaAnimator);
set.setStartDelay(delay);
set.start();
}
public boolean getIfCanAnimation() {
return ifCanAnimation;
}
public void setIfCanAnimation(boolean ifCanAnimation) {
this.ifCanAnimation = ifCanAnimation;
}
}
ObjectAnimator animator = ObjectAnimator.ofFloat(view, "alpha", 0);
AnimatorSet hiddenSet = new AnimatorSet();
hiddenSet.play(animator);
hiddenSet.setDuration(0);
hiddenSet.start();
view.measure(0,0);
ObjectAnimator oa = ObjectAnimator.ofFloat(view, "translationX", view.getMeasuredWidth(), 0);
Animator alphaAnimator = ObjectAnimator.ofFloat(view, "alpha", 0, 1);
AnimatorSet set = new AnimatorSet();
long delay = 100 * (position-1);
set.playTogether(oa,alphaAnimator);
set.setStartDelay(delay);
set.start();
/**
* 换一批动画效果
* @param position
* @param view
* @param parent
*/
private void startAnimations(int position, View view, ViewGroup parent){
animationModel.startRightAppearanceAnimation(position,view,parent);
if(getItemSize() == position){
animationModel.setIfCanAnimation(false);
}
}
animationModel.setIfCanAnimation(true);
所有评论(0)