So I have this ListView with a custom adapter that allows me to "select" an item on item clicks. Now every row of the list has an ImageView whose Drawable I change to a "selected" image when the respective item is selected. Working fine on my Lollipop device.
I construct the Drawables in the constructor of the list adapter
public DoubleRowSelectableArrayAdapter(Context context, int resource2, List<Recording> recordings) {
super(context, resource2, recordings);
idle = ContextCompat.getDrawable(context,R.drawable.idleicon);
animation = (AnimationDrawable) ContextCompat.getDrawable(context, R.drawable.animation);
}
Now, as you can see, the "selected" item is an AnimationDrawable that shall play whenever a view is selected (it is a single-select mode btw).
Views are updated in the getView method
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater layoutInflater = LayoutInflater.from(getContext());
convertView = layoutInflater.inflate(resource, null);
}
if (position == selection) {
Log.d("getView", "selection = position");
convertView.setSelected(true);
convertView.setPressed(true);
//get the imageview from the current row
final ImageView pic = ((ImageView) convertView.findViewById(R.id.iconview));
pic.setImageDrawable(animation);
}
else{
Log.d("getView","else");
convertView.setSelected(false);
convertView.setPressed(false);
//set idle icon
((ImageView) convertView.findViewById(R.id.iconview)).setImageDrawable(idle);
}
I would assume that the AnimationDrawable has a "global" state for all the list items. So starting the animation once in the constructor should let the animation play all the time, for every list item.
I managed to get the animation playing for every item, for example by starting it in the constructor or in the getView method with a post() call. However, I omitted that part of the code because I want to focus on a slightly different thing.
Here is the problem: When I select a different listitem while the animation is playing (oneshot=false), the newly selected item's animation will play if it is BELOW the old item's position BUT does NOT play if it is ABOVE the old items position in the list. So, I select the first item. Animation playing. Second item selected, animation playing. Third selected, animation playing....10th item selected, animation playing. In the other direction, this is not working. If I have the 10th item's animation playing and select one of the items with position 1-9, the animation won't play at all. I would have to wait for the end of the running animation before a new one could play.
This behaviour changes if I get the Drawable from the resources every time getView is called - then it is working absolutely fine. So in getView
AnimationDrawable d = (AnimationDrawable) getContext().getResources().getDrawable(R.drawable.animation);
pic.setImageDrawable(d);
d.start(); //or by post() call, etc. -- however working.
My wild guess is that this has something to do with View recycling in the list. What should I do to save the (expensive?) instantiation of the drawable from resources in every getView call?
Questions: Why is that? How to set the animation correctly? Is it clever to get the animation drawable from the resources for every new animation start (probably not)? How to do it right?