• Android自定义控件:动画类(十四)----实现ListView Item进入动画


    前面两篇我们讲解了使用layoutAnimation和LayoutTransition实现ViewGroup中Item加载动画的方法,但他们都各自存在问题:
    layoutAnimation虽然是API 1中就已经引入,但只能在动画初次创建时才能使用指定动画。控件创建以后,再往ViewGroup里加Item就不会再有动画。这显然是不合适的!
    LayoutTransition能够实现无论何时往ViewGroup中添加控件都可以给其中控件使用动画。但最大的问题是,它的API等级是11。而且也没有兼容包可供我们使用这个函数。
    这样问题就来了,如果我们想在兼容API 8以上的机型,完成ListView中各个Item进入时都添加动画,这要怎么来做呢?
    今天我们要完成的效果图如下:


    从效果图中可以看到,当每个Item进入的时候,都添加了动画。前面我们说了layoutAnimation和LayoutTransition所存在的问题,那抛开这两个函数,我们要如何实现Item进入动画呢? 
    别忘了,ListView在得到每个Item时会调用BaseAdapter的getView方法!getView中每一个convertView就是当前要显示的Item所对应的View,所以我们直接对convertView添加动画不就好了。 
    上面的原理理解起来并不难,下面我们就看看如何实现的吧。

    一、搭框架

    这部分,我们主要是先搭出来要实现的框架,把ListView填充起来,效果如下:


    这里实现的效果就是把listview填充起来,总共用了九张图片,listview列表循环显示这九张图片,但我在每个图片上显示了当前item所在的位置。 
    好了,下面就来看代码吧

    1、item布局(item_layout.xml)

    我们先来看看listview的Item是怎么布局的:

    [html] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. <?xml version="1.0" encoding="utf-8"?>  
    2. <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    3.               android:orientation="vertical"  
    4.               android:layout_width="fill_parent"  
    5.               android:layout_height="wrap_content">  
    6.     <ImageView  
    7.             android:id="@+id/img"  
    8.             android:layout_width="fill_parent"  
    9.             android:layout_height="250dp"  
    10.             android:scaleType="centerCrop"  
    11.             android:layout_margin="5dp"  
    12.             android:layout_gravity="center"/>  
    13.   
    14.     <TextView  
    15.             android:id="@+id/text"  
    16.             android:layout_width="wrap_content"  
    17.             android:layout_height="wrap_content"  
    18.             android:textSize="20dp"  
    19.             android:layout_gravity="center"/>  
    20.   
    21. </FrameLayout>  
    代码很好理解,从效果图中也可以看出,底部一个imageview,中间一个文字来表示当前item所在的位置。

    2、ListAdapter

    这里就是ListView的Adapter的代码位置了,完整的代码如下,然后再细讲:
    [java] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. public class ListAdapter extends BaseAdapter {  
    2.     private List<Drawable> mDrawableList = new ArrayList<>();  
    3.     private int mLength = 0;  
    4.     private LayoutInflater mInflater;  
    5.     private Context mContext;  
    6.     private ListView mListView;  
    7.   
    8.     public ListAdapter(Context context, ListView listView, List<Drawable> drawables, int length) {  
    9.         mDrawableList.addAll(drawables);  
    10.         mLength = length;  
    11.         mInflater = LayoutInflater.from(context);  
    12.         mContext = context;  
    13.         mListView = listView;  
    14.     }  
    15.   
    16.     @Override  
    17.     public int getCount() {  
    18.         return mLength;  
    19.     }  
    20.   
    21.     @Override  
    22.     public Object getItem(int position) {  
    23.         return mDrawableList.get(position % mDrawableList.size());  
    24.     }  
    25.   
    26.     @Override  
    27.     public long getItemId(int position) {  
    28.         return position;  
    29.     }  
    30.   
    31.     @Override  
    32.     public View getView(int position, View convertView, ViewGroup parent) {  
    33.         ViewHolder holder = null;  
    34.   
    35.         if (convertView == null) {  
    36.   
    37.             holder = new ViewHolder();  
    38.             convertView = mInflater.inflate(R.layout.item_layout, null);  
    39.             holder.mImageView = (ImageView) convertView.findViewById(R.id.img);  
    40.             holder.mTextView = (TextView) convertView.findViewById(R.id.text);  
    41.   
    42.   
    43.   
    44.         } else {  
    45.             holder = (ViewHolder) convertView.getTag();  
    46.         }  
    47.   
    48.         convertView.setTag(holder);  
    49.   
    50.         holder.mImageView.setImageDrawable(mDrawableList.get(position % mDrawableList.size()));  
    51.         holder.mTextView.setText(position+"");  
    52.   
    53.         return convertView;  
    54.     }  
    55.   
    56.     public class ViewHolder {  
    57.         public ImageView mImageView;  
    58.         public TextView mTextView;  
    59.     }  
    60. }  
    首先是构造函数:
    [java] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. public ListAdapter(Context context, ListView listView, List<Drawable> drawables, int length) {  
    2.     mDrawableList.addAll(drawables);  
    3.     mLength = length;  
    4.     mInflater = LayoutInflater.from(context);  
    5.     mContext = context;  
    6.     mListView = listView;  
    7. }  
    首先是传进来的几个参数,List<Drawable> drawables是listview要循环显示的图片的Drawable对象列表,length表示当前listview要显示多少行。可能有些同学会注意到,我们还把ListView对象给传进来了,然后在上面的代码中并没有用到,其中把listview封装进Adapter是一个好习惯,因为我们可能会在Adapter中监听listview的状态从而改变item的显示情况。我们这里目前还没有用到Listview 
    然后是getItem函数:
    [java] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. @Override  
    2. public Object getItem(int position) {  
    3.     return mDrawableList.get(position % mDrawableList.size());  
    4. }  
    我们知道本身的BaseAdapter并没有使用getItem(int position)函数,重写这个函数是为了让我们在BaseAdapter实例中,可以通过getItem来获取我们想要的实例(类似下面这样):
    [java] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. ListView listView = (ListView)findViewById(R.id.list);  
    2. final ListAdapter adapter = new ListAdapter(this,listView,drawables,300);  
    3. listView.setAdapter(adapter);  
    4. listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {  
    5.     @Override  
    6.     public void onItemClick(AdapterView<?> parent, View view, int position, long id) {  
    7.         //关键在这里哦  
    8.         Drawable drawable = (Drawable) adapter.getItem(position);  
    9.     }  
    10. });  
    这里我们将当前位置所对应的图片Drawable传过去:
    [java] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. public Object getItem(int position) {  
    2.     return mDrawableList.get(position % mDrawableList.size());  
    3. }  
    大家可能会疑问:为什么要用position % mDrawableList.size()来得到当前图片在图片列表中的索引?因为我们是循环显示的图片的,比如我们总共有九张图片,那当前是第12个item时,显示的应当是第3张图了,position的值为12(因为Adapter的position是从0开始的),所以12%9 = 3;这就对上了。理解不了的同学,多拿几个数来算算,比如当显示到第15张时,position是多少,对应的图片应该是哪一张呢? 
    最后getView()函数
    [java] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. public View getView(int position, View convertView, ViewGroup parent) {  
    2.    ViewHolder holder = null;  
    3.   
    4.    if (convertView == null) {  
    5.   
    6.        holder = new ViewHolder();  
    7.        convertView = mInflater.inflate(R.layout.item_layout, null);  
    8.        holder.mImageView = (ImageView) convertView.findViewById(R.id.img);  
    9.        holder.mTextView = (TextView) convertView.findViewById(R.id.text);  
    10.    } else {  
    11.        holder = (ViewHolder) convertView.getTag();  
    12.    }  
    13.   
    14.    convertView.setTag(holder);  
    15.   
    16.    holder.mImageView.setImageDrawable(mDrawableList.get(position % mDrawableList.size()));  
    17.    holder.mTextView.setText(position+"");  
    18.   
    19.    return convertView;  
    20. }  
    这段代码就不用我讲了吧,就是基本的getView用法,如果大家不理解为什么要利用 convertView.setTag(holder);的方式来重复使用convertView,可以参考这篇文章《BaseAdapter——convertView回收机制与动态控件响应》 
    在理解了convertview回收机制以后,这里最难的地方应该就是赋值的位置了:
    [java] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. holder.mImageView.setImageDrawable(mDrawableList.get(position % mDrawableList.size()));  
    2. holder.mTextView.setText(position+"");  
    根据位置找到图片的drawable我们上面已经讲过了,这也就没什么难度了,就不再细讲了。

    3、主布局(main.xml)

    主布局非常简单,就只有一个ListView控件:
    [html] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. <?xml version="1.0" encoding="utf-8"?>  
    2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    3.               android:orientation="vertical"  
    4.               android:layout_width="fill_parent"  
    5.               android:layout_height="fill_parent"  
    6.               android:background="#ffffff">  
    7.   
    8.     <ListView  
    9.             android:id="@+id/list"  
    10.             android:layout_width="fill_parent"  
    11.             android:layout_height="fill_parent"/>  
    12. </LinearLayout>  

    4、MyActivity.java

    最后是在MyActivity中构造ListAdapter并设置进listview的过程了:
    [java] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. public class MyActivity extends Activity {  
    2.   
    3.     @Override  
    4.     public void onCreate(Bundle savedInstanceState) {  
    5.         super.onCreate(savedInstanceState);  
    6.         setContentView(R.layout.main);  
    7.   
    8.   
    9.         List<Drawable> drawables = new ArrayList<>();  
    10.         drawables.add(getResources().getDrawable(R.drawable.pic1));  
    11.         drawables.add(getResources().getDrawable(R.drawable.pic2));  
    12.         drawables.add(getResources().getDrawable(R.drawable.pic3));  
    13.         drawables.add(getResources().getDrawable(R.drawable.pic4));  
    14.         drawables.add(getResources().getDrawable(R.drawable.pic5));  
    15.         drawables.add(getResources().getDrawable(R.drawable.pic6));  
    16.         drawables.add(getResources().getDrawable(R.drawable.pic7));  
    17.         drawables.add(getResources().getDrawable(R.drawable.pic8));  
    18.         drawables.add(getResources().getDrawable(R.drawable.pic9));  
    19.   
    20.   
    21.         ListView listView = (ListView)findViewById(R.id.list);  
    22.         ListAdapter adapter = new ListAdapter(this,listView,drawables,300);  
    23.         listView.setAdapter(adapter);  
    24.     }  
    25. }  
    这段代码很简单了,就是先构造图片所对应的Drawable列表,然后构造ListAdapter实例,最后设置进Listview将其显示出来,没什么难度,也没什么好讲了。 
    到这里,我们listview就构造完成了。下面就看如何向其中的item添加动画的环节了。

    二、Item添加动画——初步实现

    1、动画文件(bottom_in_anim.xml)

    先定义从底部进入的动画:
    [html] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. <?xml version="1.0" encoding="utf-8"?>  
    2. <set xmlns:android="http://schemas.android.com/apk/res/android"  
    3.      android:duration="1000">  
    4.     <translate android:fromYDelta="100%" android:toYDelta="0"/>  
    5.     <alpha android:fromAlpha="0" android:toAlpha="1"/>  
    6. </set>  
    这段动画不难理解,效果是从底部进入,alpha值从0变到1;

    2、在Adapter中添加动画代码

    首先,我们在ListAdapter中初始化的时候,加载动画:
    [java] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. public class ListAdapter extends BaseAdapter {  
    2.     …………  
    3.     private Animation animation;  
    4.   
    5.     public ListAdapter(Context context, ListView listView, List<Drawable> drawables, int length) {  
    6.         …………  
    7.         animation = AnimationUtils.loadAnimation(mContext,R.anim.bottom_in_anim);  
    8.     }  
    9.     …………  
    10. }   
    然后在getView的时候为每个convertView添加上动画
    [java] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. public View getView(int position, View convertView, ViewGroup parent) {  
    2.    ViewHolder holder = null;  
    3.   
    4.    if (convertView == null) {  
    5.   
    6.        holder = new ViewHolder();  
    7.        convertView = mInflater.inflate(R.layout.item_layout, null);  
    8.        holder.mImageView = (ImageView) convertView.findViewById(R.id.img);  
    9.        holder.mTextView = (TextView) convertView.findViewById(R.id.text);  
    10.    } else {  
    11.        holder = (ViewHolder) convertView.getTag();  
    12.    }  
    13.    convertView.startAnimation(animation);  
    14.    convertView.setTag(holder);  
    15.   
    16.    holder.mImageView.setImageDrawable(mDrawableList.get(position % mDrawableList.size()));  
    17.    holder.mTextView.setText(position+"");  
    18.   
    19.    return convertView;  
    20. }  
    让一个view开始动画非常简单,只需要调用convertView.startAnimation(animation);即可;这样就可以实现在构造item的时候就开始动画 
    ListAdapter完整代码如下
    [java] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. public class ListAdapter extends BaseAdapter {  
    2.     private List<Drawable> mDrawableList = new ArrayList<>();  
    3.     private int mLength = 0;  
    4.     private LayoutInflater mInflater;  
    5.     private Context mContext;  
    6.     private ListView mListView;  
    7.     private Animation animation;  
    8.   
    9.     public ListAdapter(Context context, ListView listView, List<Drawable> drawables, int length) {  
    10.         mDrawableList.addAll(drawables);  
    11.         mLength = length;  
    12.         mInflater = LayoutInflater.from(context);  
    13.         mContext = context;  
    14.         mListView = listView;  
    15.         animation = AnimationUtils.loadAnimation(mContext,R.anim.bottom_in_anim);  
    16.     }  
    17.   
    18.     @Override  
    19.     public int getCount() {  
    20.         return mLength;  
    21.     }  
    22.   
    23.     @Override  
    24.     public Object getItem(int position) {  
    25.         return mDrawableList.get(position % mDrawableList.size());  
    26.     }  
    27.   
    28.     @Override  
    29.     public long getItemId(int position) {  
    30.         return position;  
    31.     }  
    32.   
    33.     @Override  
    34.     public View getView(int position, View convertView, ViewGroup parent) {  
    35.         ViewHolder holder = null;  
    36.   
    37.         if (convertView == null) {  
    38.   
    39.             holder = new ViewHolder();  
    40.             convertView = mInflater.inflate(R.layout.item_layout, null);  
    41.             holder.mImageView = (ImageView) convertView.findViewById(R.id.img);  
    42.             holder.mTextView = (TextView) convertView.findViewById(R.id.text);  
    43.         } else {  
    44.             holder = (ViewHolder) convertView.getTag();  
    45.         }  
    46.         convertView.startAnimation(animation);  
    47.         convertView.setTag(holder);  
    48.   
    49.         holder.mImageView.setImageDrawable(mDrawableList.get(position % mDrawableList.size()));  
    50.         holder.mTextView.setText(position+"");  
    51.   
    52.         return convertView;  
    53.     }  
    54.   
    55.     public class ViewHolder {  
    56.         public ImageView mImageView;  
    57.         public TextView mTextView;  
    58.     }  
    59. }  
    效果图为:

    从效果图中可以看出,我们初步实现了在item生成的时候添加进入动画

    三、优化

    上面虽然解决了进入时添加动画的问题,但仔细的同学可以看出,在这个效果图中还存在几个问题,可能上面的效果图还看不清楚具体存在的问题 
    1、如果上拉的时候,一下上拉了几个item,那些要显示的item会一起从底部出现 
    2、在下拉的时候,上部出现的item也会应用上动画 

    首先,解决第二个问题比较简单,只需要判断当前手指是上滑还上下滑就可以了,只有当手指向上滑的时候,才对底部出现的item添加上入场动画,其它时间不添加动画即可 
    第一个问题其实也比较容易解决,我们可以通过listview.getChildCount()得到当前ListView中有多少个item。我们只给最后一个添加动画即可。其它的就直接显示就好了。

    1、上下滑动问题

    首先,我们首先解决上下滑动问题,这个问题其实比较好解决,只需要监听listview的OnScrollListener,根据它判断出当前ListView是上滑还是下滑就可以了。 
    先看我们在onScrollListner中都有哪些参数:

    [java] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. AbsListView.OnScrollListener mOnScrollListener = new AbsListView.OnScrollListener() {  
    2.     @Override  
    3.     public void onScrollStateChanged(AbsListView view, int scrollState) {  
    4.   
    5.     }  
    6.   
    7.     @Override  
    8.     public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {  
    9.     }  
    10. };  
    我们主要关注onScroll的监听,
    [java] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount)  
    有四个参数: 
    • 第一个参数AbsListView view:是当前listview的对象 
    • 第二个参数int firstVisibleItem:表示当前第一个可见的item在listview所有item中的索引,这里需要非常注意,firstVisibleItem与getChildAt(int position)中的参数position的意义不同,firstVisibleItem是指在整个ListView中的位置。而getChildAt(int position)中参数position传的是当前屏幕显示区域中item的索引,屏幕中第一个item的view可以通过getChildAt(0)得到。 
    • 第三个参数int visibleItemCount:表示当前屏幕中可见的有几条item 
    • 第四个参数int totalItemCount:表示当前listview总共有多少条item,得到的值与adapter.getCount()的值相同。 
    在理解了上面四个参数以后,我们再来看看下移的情况; 
    向下移动包括两种情况: 
    第一:屏幕中第一个item或前几个item一起移出屏幕,在这种情况下,我们只需要判断firstVisibleItem是否比上次的值大即可。即第一个显示的item是不是已经向下移了
    [java] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {  
    2.     /** 
    3.      * firstVisibleItem > mFirstPosition表示向下滑动一个或多个Item 
    4.      */  
    5.     isScrollDown = firstVisibleItem > mFirstPosition;  
    6.     mFirstPosition = firstVisibleItem;  
    7. }  
    第二:可能用户并没有一次性移一整条item,而是仅让当前item向上移了一点点。这里,由于当前可见的第一个item的位置仍然是firstVisibleItem,只是它的top值变了。 
    如下图:

    在这个效果图中,只是将第一个item向上移动了一点点,第一个item左上角的坐标从(0,-100)变成了(0,-200);所以从这个图中,我们可以得到如何计算在这种情况下是否上移。

    [java] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. @Override  
    2. public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {  
    3.    View firstChild = view.getChildAt(0);  
    4.    if (firstChild == nullreturn;  
    5.    int top = firstChild.getTop();  
    6.    /** 
    7.     * mFirstTop > top表示在当前这个item中滑动 
    8.     */  
    9.    isScrollDown = mFirstTop > top;  
    10.    mFirstTop = top;  
    11. }  
    只需要判断当前第一个item的左上角坐标是不是变小了即可。这里需要注意,得到屏幕中显示的第一个Item是通过ListView.getChildAt(int position)函数得到的。我们上面已经讲到,ListView.getChildAt(int position)中参数position表示的是当前item所在屏幕显示区域中的索引,屏幕中第一个item的索引是0 
    所以我们将这两种情况进行合并,得到完整的onScrollListener:
    [java] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. AbsListView.OnScrollListener mOnScrollListener = new AbsListView.OnScrollListener() {  
    2.     @Override  
    3.     public void onScrollStateChanged(AbsListView view, int scrollState) {  
    4.   
    5.     }  
    6.   
    7.     @Override  
    8.     public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {  
    9.         View firstChild = view.getChildAt(0);  
    10.         if (firstChild == nullreturn;  
    11.         int top = firstChild.getTop();  
    12.         /** 
    13.          * firstVisibleItem > mFirstPosition表示向下滑动一整个Item 
    14.          * mFirstTop > top表示在当前这个item中滑动 
    15.          */  
    16.         isScrollDown = firstVisibleItem > mFirstPosition || mFirstTop > top;  
    17.         mFirstTop = top;  
    18.         mFirstPosition = firstVisibleItem;  
    19.     }  
    20. };  
    然后在getView的时候,判断如果是向下滑动,就添加动画
    [java] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. @Override  
    2. public View getView(int position, View convertView, ViewGroup parent) {  
    3.    ViewHolder holder = null;  
    4.   
    5.    if (convertView == null) {  
    6.   
    7.        holder = new ViewHolder();  
    8.        convertView = mInflater.inflate(R.layout.item_layout, null);  
    9.        holder.mImageView = (ImageView) convertView.findViewById(R.id.img);  
    10.        holder.mTextView = (TextView) convertView.findViewById(R.id.text);  
    11.    } else {  
    12.        holder = (ViewHolder) convertView.getTag();  
    13.    }  
    14.   
    15.    if (isScrollDown) {  
    16.        convertView.startAnimation(animation);  
    17.    }  
    18.    convertView.setTag(holder);  
    19.   
    20.    holder.mImageView.setImageDrawable(mDrawableList.get(position % mDrawableList.size()));  
    21.    holder.mTextView.setText(position + "");  
    22.   
    23.    return convertView;  
    24. }  

    2、多个item同时动画问题

    由于我们只能在Item生成时给这个Item添加动画,所以要解决多个item同时移动的问题,我们只能给最后一个Item添加动画,其它item不给他们添加;但我们怎么知道当前这个item是不是要显示的最后一个item呢?无法得各,所以一个中转方案是,在每一个item在添加动画前,都把当前显示区域内所有item动画给取消,然后给当前convertView添加上动画;当listview滚动到最后一个Item的时候,自然,同样也是先把所有动画取消,然后给他自己添加上动画,所以这样看起来就好像是只给他自己添加了动画,之前滚动的item是没有动画的。 
    代码如下:
    [java] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. public View getView(int position, View convertView, ViewGroup parent) {  
    2.     ViewHolder holder = null;  
    3.   
    4.     if (convertView == null) {  
    5.   
    6.         holder = new ViewHolder();  
    7.         convertView = mInflater.inflate(R.layout.item_layout, null);  
    8.         holder.mImageView = (ImageView) convertView.findViewById(R.id.img);  
    9.         holder.mTextView = (TextView) convertView.findViewById(R.id.text);  
    10.     } else {  
    11.         holder = (ViewHolder) convertView.getTag();  
    12.     }  
    13.   
    14.     //清除当前显示区域中所有item的动画  
    15.     for (int i=0;i<mListView.getChildCount();i++){  
    16.         View view = mListView.getChildAt(i);  
    17.         view.clearAnimation();  
    18.     }  
    19.     //然后给当前item添加上动画  
    20.     if (isScrollDown) {  
    21.         convertView.startAnimation(animation);  
    22.     }  
    23.     convertView.setTag(holder);  
    24.   
    25.     holder.mImageView.setImageDrawable(mDrawableList.get(position % mDrawableList.size()));  
    26.     holder.mTextView.setText(position + "");  
    27.   
    28.     return convertView;  
    29. }  
    在这段代码中,相比上面的代码,我们只添加了一段语句:
    [java] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. for (int i=0;i<mListView.getChildCount();i++){  
    2.     View view = mListView.getChildAt(i);  
    3.     view.clearAnimation();  
    4. }  
    上面我们讲了mListView.getChildAt(int position)的用法,说到它的参数position表示的是在当前屏幕显示区域中当前item的索引。所以在当前屏幕中第一个item的索引是0;而mListView.getChildCount()则表示当前屏幕显示区域中,总共有多少个item。所以我们利用上面的代码,对屏幕显示区域中每个item进行索引,然后取消他们的动画即可。 
    此时ListAdapter完整的代码为:
    [java] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. public class ListAdapter extends BaseAdapter {  
    2.     private List<Drawable> mDrawableList = new ArrayList<>();  
    3.     private int mLength = 0;  
    4.     private LayoutInflater mInflater;  
    5.     private Context mContext;  
    6.     private ListView mListView;  
    7.     private Animation animation;  
    8.     private int mFirstTop, mFirstPosition;  
    9.     private boolean isScrollDown;  
    10.   
    11.     public ListAdapter(Context context, ListView listView, List<Drawable> drawables, int length) {  
    12.         mDrawableList.addAll(drawables);  
    13.         mLength = length;  
    14.         mInflater = LayoutInflater.from(context);  
    15.         mContext = context;  
    16.         mListView = listView;  
    17.         animation = AnimationUtils.loadAnimation(mContext, R.anim.bottom_in_anim);  
    18.         mListView.setOnScrollListener(mOnScrollListener);  
    19.     }  
    20.   
    21.     AbsListView.OnScrollListener mOnScrollListener = new AbsListView.OnScrollListener() {  
    22.         @Override  
    23.         public void onScrollStateChanged(AbsListView view, int scrollState) {  
    24.   
    25.         }  
    26.   
    27.         @Override  
    28.         public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {  
    29.             View firstChild = view.getChildAt(0);  
    30.             if (firstChild == nullreturn;  
    31.             int top = firstChild.getTop();  
    32.             /** 
    33.              * firstVisibleItem > mFirstPosition表示向下滑动一整个Item 
    34.              * mFirstTop > top表示在当前这个item中滑动 
    35.              */  
    36.             isScrollDown = firstVisibleItem > mFirstPosition || mFirstTop > top;  
    37.             mFirstTop = top;  
    38.             mFirstPosition = firstVisibleItem;  
    39.         }  
    40.     };  
    41.   
    42.     @Override  
    43.     public int getCount() {  
    44.         return mLength;  
    45.     }  
    46.   
    47.     @Override  
    48.     public Object getItem(int position) {  
    49.         return mDrawableList.get(position % mDrawableList.size());  
    50.     }  
    51.   
    52.     @Override  
    53.     public long getItemId(int position) {  
    54.         return position;  
    55.     }  
    56.   
    57.     @Override  
    58.     public View getView(int position, View convertView, ViewGroup parent) {  
    59.         ViewHolder holder = null;  
    60.   
    61.         if (convertView == null) {  
    62.   
    63.             holder = new ViewHolder();  
    64.             convertView = mInflater.inflate(R.layout.item_layout, null);  
    65.             holder.mImageView = (ImageView) convertView.findViewById(R.id.img);  
    66.             holder.mTextView = (TextView) convertView.findViewById(R.id.text);  
    67.         } else {  
    68.             holder = (ViewHolder) convertView.getTag();  
    69.         }  
    70.   
    71.         //清除当前显示区域中所有item的动画  
    72.         for (int i=0;i<mListView.getChildCount();i++){  
    73.             View view = mListView.getChildAt(i);  
    74.             view.clearAnimation();  
    75.         }  
    76.         //然后给当前item添加上动画  
    77.         if (isScrollDown) {  
    78.             convertView.startAnimation(animation);  
    79.         }  
    80.         convertView.setTag(holder);  
    81.   
    82.         holder.mImageView.setImageDrawable(mDrawableList.get(position % mDrawableList.size()));  
    83.         holder.mTextView.setText(position + "");  
    84.   
    85.         return convertView;  
    86.     }  
    87.   
    88.     public class ViewHolder {  
    89.         public ImageView mImageView;  
    90.         public TextView mTextView;  
    91.     }  
    92. }  
    到这里,有关listview中添加动画的部分就结束了,下面来看一下最终的效果图吧:

    源码在文章底部给出


    如果本文有帮到你,记得加关注哦

    源码下载地址:http://download.csdn.net/detail/harvic880925/9474080

    请大家尊重原创者版权,转载请标明出处: http://blog.csdn.net/harvic880925/article/details/50988685 谢谢


  • 相关阅读:
    js过滤HTML标签以及&nbsp;
    Sharepoint的web.config配置
    javascript 动态添加div等这样的标签包含一些元素
    SPMetal 日志导出Caml语句
    sitepage applicationPage 区别
    exchange部署的好处
    SPSiteDataQuery不完全使用手册
    WP7 开发(十二) WebBrowser控件
    WP7 开发(十一) Web Task
    WP7 开发(十四) ApplicationBar
  • 原文地址:https://www.cnblogs.com/vegetate/p/9997291.html
Copyright © 2020-2023  润新知