Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Animate ListView items on notifyDataSetChanged()

I want to add some animation to my ListView with SimpleCursorAdapter when my DB data changes. I am using SimpleCursorAdapter with LoaderManager I tried to add animation in getView method

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View view=super.getView(position, convertView, parent);
    //My animation(nineoldandroid)
    ObjectAnimator.ofFloat(view,"alpha",0,1).setDuration(500).start();
    return view;
}

But this method animates all items, although some items were the same before updating. Does Android have methods to detect which items need update, remove or add?

For example, maybe there are methods for getting changes between old and new cursor before calling myAdapter.swapCursor(newCursor); It would be possible to mark items(removed, updated, new) and make removing animation before swapping and ither animation in getView. How can I solve this problem?

like image 450
sagus_helgy Avatar asked Nov 11 '14 08:11

sagus_helgy


People also ask

How to get data from ListView by clicking item on ListView?

Try this: my_listview. setOnItemClickListener(new OnItemClickListener() { public void onItemClick(AdapterView<?> parent, View view, int position, long id) { } });

How to edit ListView item in android?

OnItemClickListener MshowforItem = new AdapterView. OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { ((TextView)view). setText("Hello"); } };

What does notifyDataSetChanged do in Recyclerview?

notifyDataSetChanged. Notify any registered observers that the data set has changed. There are two different classes of data change events, item changes and structural changes. Item changes are when a single item has its data updated but no positional changes have occurred.


2 Answers

There are many ways to achieve this, you can try the answers in this question :

How to Animate Addition or Removal of Android ListView Rows

The 1st answer is working

like image 66
Blaze Tama Avatar answered Oct 08 '22 23:10

Blaze Tama


No, at least I haven't found that Android can report to me if there are new or deleted items. I made something similar where the items of the ListView animate to their new positions and I had to track their positions myself to do that.

For your use case, it is probably easier to put the fading animation just before you delete the row from the database. So wherever in your code it is that you delete the row from the database and trigger a refresh, you do the fade animation on the item and on completion of the animation you delete the row and trigger a refresh.

Update

Hmmm, I read too quickly. Your example is not a fade-out on deleted items, but a fade-in on new items.

You will have to track item IDs yourself in your adapter. This approach can only work if you have a limited number of items to show because the list of previous item IDs will have to be stored in memory. If you can not be certain the list is never too large then you'll have to find a way to add the 'newness' information to the cursor itself.

Let me see if I can cook something up. Be back later...

Update 2

Below is a SimpleCursorAdapter that keeps track of the item ID from the previous cursor. In getView() it kicks of the fade-in animation if the requested view is for an item that was not present before.

private static class FadeInAdapter extends SimpleCursorAdapter {

    private List<Long> previousItemIds = new ArrayList<Long>();

    private FadeInAdapter(Context context, int layout, Cursor c, String[] from, int[] to, int flags) {
        super(context, layout, c, from, to, flags);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View result = super.getView(position, convertView, parent);

        // check if this view is for an item that is new
        long itemId = getItemId(position);
        if (!previousItemIds.contains(itemId)) {
            // do the fade-in animation
            result.setAlpha(0);
            result.animate().alpha(1).setDuration(500).start();
        }

        return result;
    }

    @Override
    public void changeCursor(Cursor cursor) {
        Cursor oldCursor = getCursor();
        if (oldCursor != null) {
            // store previous item IDs to check against for newness with the new cursor
            final int idColumnIndex = oldCursor.getColumnIndexOrThrow(DatabaseContract._ID);
            previousItemIds.clear();
            for (oldCursor.moveToFirst(); !oldCursor.isAfterLast(); oldCursor.moveToNext()) {
                previousItemIds.add(oldCursor.getLong(idColumnIndex));
            }
        }

        super.changeCursor(cursor);
    }
}
like image 42
Rob Meeuwisse Avatar answered Oct 09 '22 01:10

Rob Meeuwisse