animate listView childs only once they appear

2019-03-20 04:59发布

问题:

I have a listView with about 20 items (dynamic items). I want to animate these items first they show up to user. something like Google+ cards. There are some points that I want to achieve:

  1. items animate only when the user starts to see them.
  2. items animate only once. (not every time user sees them)
  3. on fast scrolling items don't mess up to each other.
  4. animations start with a delay according to position of items.

Up to now I have tried:

  • LayoutAnimationController (this method didn't meet the first requirement)
  • convertView.startAnimation (this method didn't meet the second requirement)
  • convertView.startAnimation with a flag that if the item at position has been animated before or not (this method didn't work for first items in listView because, the getView method will be called twice for first items in listView. (I don't know why! layout_height and layout_width are both match_parent))

I searched a lot but couldn't come along with a solution.

By the way, I prefer not to use external libraries. I have seen this before.

Thanks.

回答1:

I've just tried this and it seems to meet all of your requirements:

boolean[] animationStates;

public void YourConstructor(...) {
    ...
    animationStates = new boolean[data.size()];
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    // (Re)Use the convertView
    if (convertView == null) {
        convertView = mInflater.inflate(R.layout.popup_list_item, parent, false);
        if (!animationStates[position]) {
            Log.e("TAG", "Animating item no: " + position);
            animationStates[position] = true;
            Animation animation = AnimationUtils.loadAnimation(mContext, R.anim.fade_in);
            animation.setStartOffset(position*500);
            convertView.startAnimation(animation);
        }
    }
    // Use convertView here
    return convertView;
}

Here's my fade_in.xml file if you're interested:

<set
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:fillAfter="true">
    <alpha
        android:duration="1000"
        android:fromAlpha="0.0"
        android:toAlpha="1.0"/>
</set>