Android animate all listview items simultaneously
Asked Answered
H

1

6

I want to achieve simultaneous animation on all list view items to put it into edit mode. Here is effect identical to what Im going for: http://youtu.be/cFSRusFkI_I?t=2m6s My list item layout code:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/item_content"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="4dp" >

    <CheckBox
        android:id="@+id/checkbox"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_centerVertical="true"
        android:visibility="invisible" />

    <TextView
        android:id="@+id/nameTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_centerVertical="true"
        android:textSize="16sp"
        android:textStyle="bold" />

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:paddingRight="5dip"
        android:src="@drawable/right_arrow" />

</RelativeLayout>

After user clicks button in actionBar I want to animate sliding checkboxes slide from left to right, with proper animation of textview, to make space for checkboxes. I left checkbox invisible for purpose, to measure its width for animation. Method I use for animating checboxes (hide or show, it depend from state paramater):

public void setListHandlesVisibleState(boolean state) {
    AnimatorSet as = new AnimatorSet();
    int childCount = mListView.getChildCount();
    ArrayList<Animator> list = new ArrayList<Animator>();
    for (int i = 0; i<childCount; ++i) {
        CheckBox v = (CheckBox) mListView.getChildAt(i).findViewById(
                R.id.checkbox);
        TextView tv = (TextView) mListView.getChildAt(i).findViewById(
                R.id.nameTextView);
        if (state) {
            list.add(ObjectAnimator.ofFloat(v, "x", -v.getWidth(),
                    v.getLeft()));
            list.add(ObjectAnimator.ofFloat(v, "alpha", 0, 1));
            list.add(ObjectAnimator.ofFloat(tv, "x", tv.getLeft(),
                    (float) (v.getWidth() * 0.9)));
        } else {
            list.add(ObjectAnimator.ofFloat(v, "x", v.getLeft(),
                    -v.getWidth()));
            list.add(ObjectAnimator.ofFloat(v, "alpha", 1, 0));
            list.add(ObjectAnimator.ofFloat(tv, "x",
                    (float) (v.getWidth() * 0.9), tv.getLeft()));
        }
    }
    as.addListener(this);
    as.playTogether(list);
    as.setDuration(200);
    as.start();
}
@Override
public void onAnimationEnd(Animator animation) {
    mAdapter.notifyDataSetChanged();
}

When listview is shorter than one screen (there is no view reusing) animation looks perfect and is really smooth. When list view is longer, it seems like some of listview items are not yet created, thus not animated. I tried to create view cache in adapter and use those views instead using convertView in adapter getView method, and play animations on views contained in that cache. I've also noticed that all reusable view are created when listview is created (when I scroll listview convert view is always != null). before animation

after animation

after animation and scroll

Harmon answered 11/6, 2013 at 10:38 Comment(1)
I also want to implement something like you, can you please post here whole code or give me link so that I can help you and I also can use that codeSoileau
P
0

Check out this DevBytes video about animating ListViews.

The solution is to use a StableArrayAdapter (direct link to code). This prevents the View objects from being recycled out from under you while you perform your animations.

private class StableArrayAdapter extends ArrayAdapter<String> {

    HashMap<String, Integer> mIdMap = new HashMap<String, Integer>();

    public StableArrayAdapter(Context context, int textViewResourceId,
            List<String> objects) {
        super(context, textViewResourceId, objects);
        for (int i = 0; i < objects.size(); ++i) {
            mIdMap.put(objects.get(i), i);
        }
    }

    @Override
    public long getItemId(int position) {
        String item = getItem(position);
        return mIdMap.get(item);
    }

    @Override
    public boolean hasStableIds() {
        return true;
    }

}

You might also find this video helpful.

Pricilla answered 24/3, 2015 at 21:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.