Last active
January 21, 2016 10:29
-
-
Save Judas/53b44c3166c4f03348f2 to your computer and use it in GitHub Desktop.
Animated Adapter for RecyclerView with model use-case
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.judas.protos.recyclerview.adapters; | |
import android.support.v7.widget.RecyclerView; | |
import java.util.ArrayList; | |
import java.util.Comparator; | |
import java.util.List; | |
public abstract class AnimatedAdapter<VH extends RecyclerView.ViewHolder, T> extends RecyclerView.Adapter<VH> { | |
protected List<T> mOldItems; | |
protected List<T> mNewItems; | |
// Comparator for notifyItemChanged (return something other than 0 to update the item) | |
protected Comparator<T> mUpdateComparator; | |
public void notifyUpdate() { | |
final List<T> tmpItems = new ArrayList<>(mOldItems); | |
// 1 - Deleted items must be removed | |
for (int i = mOldItems.size() - 1; i >= 0; i--) { | |
if (!mNewItems.contains(mOldItems.get(i))) { | |
notifyItemRemoved(i); | |
tmpItems.remove(i); | |
} | |
} | |
// 2 - Added items must be inserted | |
for (int i = 0; i < mNewItems.size(); i++) { | |
final T newItem = mNewItems.get(i); | |
if (!mOldItems.contains(newItem)) { | |
notifyItemInserted(i); | |
tmpItems.add(i, newItem); | |
} | |
} | |
// 3 - Items that switched place must be moved | |
T misplacedItem = getMisplacedItem(tmpItems); | |
while (misplacedItem != null) { | |
final int oldPosition = tmpItems.indexOf(misplacedItem); | |
final int newPosition = mNewItems.indexOf(misplacedItem); | |
notifyItemMoved(oldPosition, newPosition); | |
final T misplaced = tmpItems.remove(oldPosition); | |
tmpItems.add(newPosition, misplaced); | |
misplacedItem = getMisplacedItem(tmpItems); | |
} | |
// 4 - Items with new content must be updated | |
if (mUpdateComparator != null) { | |
for (int i = mNewItems.size() - 1; i >= 0; i--) { | |
final T newItem = mNewItems.get(i); | |
final T oldItem = tmpItems.get(i); | |
if (mUpdateComparator.compare(oldItem, newItem) != 0) { | |
notifyItemChanged(i); // Item at i has changed | |
} | |
} | |
} | |
} | |
private T getMisplacedItem(final List<T> tmpItems) { | |
for (int i = 0; i < tmpItems.size(); i++) { | |
final T oldItem = tmpItems.get(i); | |
final int newPosition = mNewItems.indexOf(oldItem); | |
if (i != newPosition) | |
return oldItem; | |
} | |
return null; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.judas.protos.recyclerview.activities; | |
import android.graphics.Color; | |
import android.os.Bundle; | |
import android.os.Handler; | |
import android.support.v7.app.AppCompatActivity; | |
import android.support.v7.widget.DefaultItemAnimator; | |
import android.support.v7.widget.LinearLayoutManager; | |
import android.support.v7.widget.RecyclerView; | |
import android.support.v7.widget.SimpleItemAnimator; | |
import com.judas.protos.recyclerview.R; | |
import com.judas.protos.recyclerview.adapters.ItemAdapter; | |
import com.judas.protos.recyclerview.model.Item; | |
import java.util.ArrayList; | |
import java.util.List; | |
public class HomeActivity extends AppCompatActivity { | |
private ItemAdapter mAdapter; | |
@Override | |
protected void onCreate(Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
setContentView(R.layout.main); | |
mAdapter = new ItemAdapter(); | |
final RecyclerView rv = (RecyclerView) findViewById(R.id.recycler); | |
rv.setHasFixedSize(true); | |
rv.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)); | |
rv.setAdapter(mAdapter); | |
final SimpleItemAnimator animator = new DefaultItemAnimator(); | |
animator.setAddDuration(250); | |
animator.setRemoveDuration(250); | |
animator.setMoveDuration(500); | |
animator.setChangeDuration(500); | |
rv.setItemAnimator(animator); | |
} | |
private void reset() { | |
final List<Item> items = new ArrayList<>(); | |
items.add(new Item("Item n°1", Color.RED, 1)); | |
items.add(new Item("Item n°2", Color.GREEN, 2)); | |
items.add(new Item("Item n°3", Color.BLUE, 3)); | |
items.add(new Item("Item n°4", Color.YELLOW, 4)); | |
items.add(new Item("Item n°5", Color.CYAN, 5)); | |
mAdapter.update(items, false); | |
} | |
private void shuffle() { | |
final List<Item> items = new ArrayList<>(); | |
items.add(new Item("Item n°6", Color.MAGENTA, 6)); | |
items.add(new Item("Item n°2", Color.GREEN, 2)); | |
items.add(new Item("Item n°3", Color.BLUE, 3)); | |
items.add(new Item("Item n°1 UPDATED", Color.RED, 1)); | |
items.add(new Item("Item n°4", Color.YELLOW, 4)); | |
mAdapter.update(items, true); | |
} | |
@Override | |
protected void onPostResume() { | |
super.onPostResume(); | |
// Reset to original position | |
reset(); | |
// Shuffle items after a delay | |
new Handler().postDelayed(() -> shuffle(), 2000); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.judas.protos.recyclerview.model; | |
public class Item { | |
private String mName; | |
private int mColor; | |
private int mId; | |
public Item(final String name, final int color, final int id) { | |
mName = name; | |
mColor = color; | |
mId = id; | |
} | |
public void setName(final String name) { | |
mName = name; | |
} | |
public String getName() { | |
return mName; | |
} | |
public int getColor() { | |
return mColor; | |
} | |
@Override | |
public boolean equals(final Object o) { | |
if (o == null || !(o instanceof Item)) | |
return false; | |
return mId == ((Item) o).mId; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.judas.protos.recyclerview.adapters; | |
import android.view.View; | |
import android.view.ViewGroup; | |
import android.widget.Toast; | |
import com.judas.protos.recyclerview.R; | |
import com.judas.protos.recyclerview.model.Item; | |
import java.util.ArrayList; | |
import java.util.List; | |
public class ItemAdapter extends AnimatedAdapter<ItemViewHolder, Item> { | |
public ItemAdapter() { | |
// Set comparator for animation update (compare name fields) | |
mUpdateComparator = (lhs, rhs) -> lhs.getName().compareTo(rhs.getName()); | |
} | |
public ItemAdapter(final List<Item> items) { | |
this(); | |
mNewItems = items; | |
} | |
@Override | |
public ItemViewHolder onCreateViewHolder(final ViewGroup parent, final int viewType) { | |
final View v = View.inflate(parent.getContext(), R.layout.item, null); | |
final ItemViewHolder holder = new ItemViewHolder(v); | |
v.setOnClickListener(v1 -> Toast.makeText(parent.getContext(), mNewItems.get(holder.getAdapterPosition()).getName(), Toast.LENGTH_SHORT).show()); | |
return holder; | |
} | |
@Override | |
public void onBindViewHolder(final ItemViewHolder holder, final int position) { | |
holder.bind(getItem(position)); | |
} | |
@Override | |
public int getItemCount() { | |
return mNewItems == null ? 0 : mNewItems.size(); | |
} | |
private Item getItem(final int position) { | |
if (mNewItems == null || mNewItems.size() < position) | |
return null; | |
return mNewItems.get(position); | |
} | |
public void update(final List<Item> newItems, final boolean animated) { | |
if (mNewItems == null || !animated) { | |
mNewItems = newItems; | |
notifyDataSetChanged(); | |
} else { | |
mOldItems = new ArrayList<>(mNewItems); | |
mNewItems = newItems; | |
notifyUpdate(); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.judas.protos.recyclerview.adapters; | |
import android.support.v7.widget.RecyclerView; | |
import android.view.View; | |
import android.widget.TextView; | |
import com.judas.protos.recyclerview.R; | |
import com.judas.protos.recyclerview.model.Item; | |
public class ItemViewHolder extends RecyclerView.ViewHolder { | |
private View mView; | |
public ItemViewHolder(final View v) { | |
super(v); | |
mView = v; | |
} | |
public void bind(final Item item) { | |
((TextView) mView.findViewById(R.id.item_text)).setText(item.getName()); | |
mView.findViewById(R.id.item_avatar).setBackgroundColor(item.getColor()); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment