Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Animate the removal of a ListView item

I'm attempting to animate the removal of a ListView item using this:

    mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> adapterView, final View view, final int i, long l) {
            view.animate().setDuration(500).x(-view.getWidth()).alpha(0f);
            adapter.remove(tasks.get(i));
            adapter.notifyDataSetChanged();
        }
    });

It does not work. I basically followed the advice of the 4th answer from the top of this post:

How to Animate Addition or Removal of Android ListView Rows

However, there's some funny drawing stuff going on, or recycling, or something because while the animation occurs, the item below the one that slides off screen also gets deleted for some reason. The answer that the question asker eventually marked as correct is unfortunately an RTFM towards the whole of Android's source. I've looked through there, and I can't find the notifications pull-down in JellyBean which I'm trying to emulate.

TIA. John

like image 974
John Wheeler Avatar asked Sep 26 '12 06:09

John Wheeler


3 Answers

Idea: I start animation when the user selects the row. When the animation is complete i remove the row from the adapter.The following code animates the selected row:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    final ListView listView = (ListView) findViewById(R.id.listView1);
    final ArrayList<String> values = new ArrayList<String>();
    values.add("Android");
    values.add("iPhone");
    values.add("WindowsMobile");
    values.add("Blackberry");
    values.add("Windows7");

    final ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
            android.R.layout.simple_list_item_1, android.R.id.text1, values);
    listView.setAdapter(adapter);

    final Animation animation = AnimationUtils.loadAnimation(this,
            R.anim.slide_out);
    animation.setAnimationListener(new AnimationListener() {
        @Override
        public void onAnimationStart(Animation animation) {
        }

        @Override
        public void onAnimationRepeat(Animation animation) {
        }

        @Override
        public void onAnimationEnd(Animation animation) {
            adapter.remove(adapter.getItem(selectedRow));
            adapter.notifyDataSetChanged();
        }
    });

    listView.setOnItemClickListener(new OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view,
                int position, long id) {
            Toast.makeText(getApplicationContext(),
                    " " + values.get(position), Toast.LENGTH_LONG).show();
            view.startAnimation(animation);
            selectedRow = position;

        }

    });
}

slide_out.xml file:

<?xml version="1.0" encoding="utf-8"?>
 <set xmlns:android="http://schemas.android.com/apk/res/android" >  
    <translate 
        android:fromYDelta="0%" 
        android:toYDelta="100%"  
        android:duration="@android:integer/config_mediumAnimTime"/>  
</set> 
like image 123
Alexey Avatar answered Nov 15 '22 05:11

Alexey


I just found a beautiful solution: https://github.com/paraches/ListViewCellDeleteAnimation

Here is video: http://www.youtube.com/watch?v=bOl5MIti7n0

Many thanks to 'paraches' ;)

Edit

As of Android version 22.0.0 the new android.support.v7.widget.RecyclerView is available as a successor of ListView. Standard add/remove/update animations are available out of the box. The widget animations are also easy to customize (few custom animations).

I strongly recommend switching from ListView to RecyclerView if you need custom item animations.

like image 20
Michal Vician Avatar answered Nov 15 '22 04:11

Michal Vician


As Chet Haase points out in DevBytes, https://www.youtube.com/watch?v=8MIfSxgsHIs, all of this will work but don't forget to add transientState flags.

From his code:

// Here's where the problem starts - this animation will animate a View object.
                    // But that View may get recycled if it is animated out of the container,
                    // and the animation will continue to fade a view that now contains unrelated
                    // content.
                    ObjectAnimator anim = ObjectAnimator.ofFloat(view, View.ALPHA, 0);
                    anim.setDuration(1000);
                    if (setTransientStateCB.isChecked()) {
                        // Here's the correct way to do this: if you tell a view that it has
                        // transientState, then ListView ill avoid recycling it until the
                        // transientState flag is reset.
                        // A different approach is to use ViewPropertyAnimator, which sets the
                        // transientState flag internally.
                        view.setHasTransientState(true);
                    }
                    anim.addListener(new AnimatorListenerAdapter() {
                        @Override
                        public void onAnimationEnd(Animator animation) {
                            cheeseList.remove(item);
                            adapter.notifyDataSetChanged();
                            view.setAlpha(1);
                            if (setTransientStateCB.isChecked()) {
                                view.setHasTransientState(false);
                            }
                        }
                    });
                    anim.start();
like image 4
AllDayAmazing Avatar answered Nov 15 '22 03:11

AllDayAmazing