当滑动ListView时,让当前最后可见的Item在滑进屏幕时有一个推进动画效果~

来源:互联网 发布:mac 212 刷 编辑:程序博客网 时间:2024/06/17 12:43

        最近知乎玩的比较多,某日玩知乎的版本号1.8的android客户端的时候,在浏览“发现”页下的消息列表的时候,看到每最底部的Item要滑进屏幕都会有一个向上推进的动画效果,diao炸天的感觉,网上查找多日,才知道是github上一个热门的开源项目ListViewAnimations里面提供的库所包含的动画效果,当然,这个库里面有很多很牛b的特效,这里就不详细描述了,本篇主要是做个山寨(真的很山寨-_-#)的推进特效,能在android 2.3上实现这个动画(因为这个开源的库有点复杂,现在都没理清,而且用的动画是Android 3.0之后引入的属性动画,所以2.3以前android版本不支持)。

        先写一个向上滑动的动画anim_swing_in_bottom.xml :

<?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android"    android:interpolator="@android:anim/linear_interpolator">    <translate android:fromYDelta="50%"        android:toYDelta="0"        android:duration="800"/>    <alpha android:fromAlpha="0.5"        android:toAlpha="1.0"        android:duration="500"/></set>

        然后自定义一个AnimationAdapter,继承自BaseAdapter,并且实现AbsListView.OnScrollListener接口:

public abstract class AnimationAdapter extends BaseAdapter implements OnScrollListener{    private BaseAdapter mBaseAdapter;    private AbsListView mAbsLv;    private int mFirstVisibleItemPosition = 0;    private int mLastVisibleItemPosition = -1;    private int mCurScrollState = SCROLL_STATE_IDLE;    private boolean isForwardDown = true;    //使用android提供的封装的SparseArray,优化过的hashmap,提供更好的性能    private SparseArray<View> mListItemView = new SparseArray<View>();    private View mFirstVisibleItemView, mLastVisibleItemView;    public AnimationAdapter(BaseAdapter adapter, AbsListView absListView) {        mBaseAdapter = adapter;        mAbsLv = absListView;        //这里设置传入的ListView的OnScrollListener        absListView.setOnScrollListener(this);    }    .......}

        然后再实现onScroll()方法:

    @Override    public void onScroll(AbsListView view, int firstVisibleItem,            int visibleItemCount, int totalItemCount) {        //当前处于touch scroll状态时处理,上次保存的mLastVisibleItemPosition小于当前的最后可见的item的position时,表示当前处于用户用手向上拖动ListView的场景        if(mCurScrollState == SCROLL_STATE_TOUCH_SCROLL &&                mLastVisibleItemPosition < view.getLastVisiblePosition() &&                view.getLastVisiblePosition() == firstVisibleItem + visibleItemCount - 1) {            //取消旧的底部item的动画            mLastVisibleItemView = mListItemView.get(view.getLastVisiblePosition() - 1);            if(mLastVisibleItemView != null)                mLastVisibleItemView.clearAnimation();            //获取新的底部的item,并播放动画            mLastVisibleItemView = mListItemView.get(view.getLastVisiblePosition());            if(mLastVisibleItemView != null &&                    mLastVisibleItemView.getBottom() <= view.getBottom()) {                mLastVisibleItemView.clearAnimation();            } else {                mLastVisibleItemView.startAnimation(getSwingInBottomAnimation());            }        }        mFirstVisibleItemPosition = firstVisibleItem;        mLastVisibleItemPosition = firstVisibleItem + visibleItemCount - 1;    }

        当前这个自定义的AnimationAdapter,重写其getView()方法, 其中mBaseAdapter是构造方法里面传入的是为ListView实现的BaseAdapter,本AnimationAdapter将包裹这个BaseAdapter,进行额外的处理,生成动画效果:

    @Override    public View getView(int position, View convertView, ViewGroup parent) {        convertView = mBaseAdapter.getView(position, convertView, parent);        mListItemView.put(position, convertView);        convertView.clearAnimation();        return convertView;    }
        然后再某个Activity里初始化一个ListView时,可以进行如下封装,使该ListView具有额外的动画效果:

        mLv = (ListView)findViewById(R.id.listView);        //MyAdapter就是为这个ListView实现的一个BaseAdapter实例        mAdapter = new MyAdapter(this, 30);        //装饰器模式,使用AnimationAdapter包裹该MyAdapter对象        AnimationAdapter mAnimAdapter = new AnimationAdapter(mAdapter, mLv);        mLv.setAdapter(mAnimAdapter);

        动画的具体实现就是有AnimationAdapter完成,该自定义的Adapter可以包裹其他BaseAdapter,实现通用性。不过,AnimationAdapter为对应的ListView设置了OnScrollListener,所以ListView假设原先有设置OnScrollListener的话,就会对ListView产生影响,这个暂时没想到什么好的方法解决。

        Demo上传到了github上:https://github.com/YoungLeeForeverBoy/DemoSwingInBottomAnim


原创粉丝点击