animate listView childs only once they appear
Asked Answered
K

1

7

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.

Kip answered 7/8, 2014 at 22:52 Comment(4)
Please tell me you have a good reason for avoiding external libraries. Especially open source libraries. Learning, perhaps?Spoofery
@Spoofery well I think I have to do it once before using external libraries for learning, and I think this should be an easy thing. Besides external libraries adds to final APK size, which is a negative point in downloading for users.Kip
Reading external libraries is a good way to learn, though. That's one reason people open source things :) Also, I've worked on teams where members have habits of avoiding libraries, and it can really impact delivery dates, code quality, and maintenance levels - without any justifiable reasoning. Your comment about libs gave me a weird vibe. Sometimes the external library is overkill and can be skipped, absolutely. It should just be a well thought out decision, and proguard strips code that you aren't using for production, so reasonably sized libraries aren't that scary.Spoofery
@Spoofery I never like to invent the wheel again, but in this special question it was a challenge that I wanted to solve it by myself, because I thought that it must not be a hard question. By the way, thanks for good helping :)Kip
F
8

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>
Fellatio answered 7/8, 2014 at 23:15 Comment(2)
Thanks for your reply. I tried this method, but this one doesn't meet the third requirement. As you know listView uses recycled views. this means when you scroll the page fast items don't play animation.Kip
@NavidEivazzadeh please explain the 3rd requirement more then. Mess up doesn't make much sense :-)Fellatio

© 2022 - 2024 — McMap. All rights reserved.