Skip to content

Instantly share code, notes, and snippets.

@jirivrany
Created January 10, 2016 20:22
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save jirivrany/f1f177b7bbc187e8f980 to your computer and use it in GitHub Desktop.
Save jirivrany/f1f177b7bbc187e8f980 to your computer and use it in GitHub Desktop.
Example of undo action for Android RecyclerView onSwipe.
public class PhotoAdapter extends RecyclerView.Adapter<PhotoAdapter.PhotoViewHolder> implements View.OnClickListener {
private ArrayList<Photo> photos;
public ArrayList<Photo> photosToRemove;
private OnItemClickListener onItemClickListener;
private Context context;
public PhotoAdapter(Context context, ArrayList<Photo> photos, Map<Integer, String> authors, int colHeigth) {
this.photos = photos;
this.context = context;
this.photosToRemove = new ArrayList<>();
}
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
this.onItemClickListener = onItemClickListener;
}
@Override
public PhotoViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_myphotos, parent, false);
v.setOnClickListener(this);
BusProvider.getInstance().register(this);
PhotoViewHolder photoViewHolder = new PhotoViewHolder(v);
return photoViewHolder;
}
@Override
public void onBindViewHolder(PhotoViewHolder holder, int position) {
Photo photo = photos.get(position);
String tempUrl = context.getFilesDir() + UrlBuilder.localCoverPhoto(photo.remoteId);
Glide.with(context)
.load(tempUrl)
.centerCrop()
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(holder.photoCover);
holder.itemView.setTag(photo);
}
@Override
public void onViewRecycled(PhotoViewHolder holder) {
super.onViewRecycled(holder);
Glide.clear(holder.photoCover);
}
@Override
public int getItemCount() {
return photos.size();
}
@Override
public void onClick(final View v) {
// Give some time to the ripple to finish the effect
if (onItemClickListener != null) {
new Handler().postDelayed(new Runnable() {
@Override public void run() {
onItemClickListener.onItemClick(v, (Photo) v.getTag());
}
}, 50);
}
}
public void onItemRemove(final RecyclerView.ViewHolder viewHolder, final RecyclerView mRecyclerView) {
final int adapterPosition = viewHolder.getAdapterPosition();
final Photo mPhoto = photos.get(adapterPosition);
Snackbar snackbar = Snackbar
.make(mRecyclerView, context.getString(R.string.removed_from_device), Snackbar.LENGTH_LONG)
.setAction(R.string.undo, new View.OnClickListener() {
@Override
public void onClick(View view) {
int mAdapterPosition = viewHolder.getAdapterPosition();
photos.add(mAdapterPosition, mPhoto);
notifyItemInserted(mAdapterPosition);
mRecyclerView.scrollToPosition(mAdapterPosition);
photosToRemove.remove(mPhoto);
}
});
snackbar.show();
photos.remove(adapterPosition);
notifyItemRemoved(adapterPosition);
photosToRemove.add(mPhoto);
}
public static class PhotoViewHolder extends RecyclerView.ViewHolder {
ImageView photoCover;
public PhotoViewHolder(View itemView) {
super(itemView);
photoCover = (ImageView) itemView.findViewById(R.id.catalog_photo_cover);
}
}
public interface OnItemClickListener {
void onItemClick(View view, Photo photo);
}
}
public class PhotoFragment extends Fragment implements PhotoAdapter.OnItemClickListener {
public static final String TAG = "PhotoFragment";
private int colsNr;
private ArrayList<Photo> photos;
PhotoAdapter mAdapter;
@Bind(R.id.catalog_rv)
RecyclerView recyclerView;
@Bind(R.id.catalog_empty_view)
LinearLayout emptyView;
public static PhotoFragment newInstance() {
PhotoFragment fragment = new PhotoFragment();
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
colsNr = getResources().getInteger(R.integer.main_grid_columns);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View view = inflater.inflate(R.layout.fragment_store_main, container, false);
ButterKnife.bind(this, view);
GridLayoutManager gridLayoutManager = new GridLayoutManager(getContext(), colsNr);
recyclerView.setLayoutManager(gridLayoutManager);
return view;
}
@Override
public void onResume() {
super.onResume();
photos = (ArrayList<Photo>) Photo.getAllDownloaded();
refreshAdapter();
if (photos.isEmpty()) {
showEmptyView();
}
else {
hideEmptyView();
mAdapter = new PhotoAdapter(getContext(), photos, authorIndex, colHeigth);
mAdapter.setOnItemClickListener(this);
recyclerView.swapAdapter(mAdapter, false);
ItemTouchHelper.Callback callback = new PhotoTouchHelper(mAdapter, recyclerView);
ItemTouchHelper helper = new ItemTouchHelper(callback);
helper.attachToRecyclerView(recyclerView);
}
}
@Override
public void onPause() {
ArrayList<Integer> photoIds = new ArrayList<>();
if (mAdapter != null) {
if (mAdapter.photosToRemove != null) {
for (Photo photo: mAdapter.photosToRemove){
photoIds.add(photo.remoteId);
}
Intent mServiceIntent = new Intent(getActivity(), PhotoRemoveService.class);
mServiceIntent.putExtra(Constants.ARG_GUIDES_TO_DELETE, photoIds);
getActivity().startService(mServiceIntent);
}
}
super.onPause();
}
private void showEmptyView() {
recyclerView.setVisibility(View.GONE);
emptyView.setVisibility(View.VISIBLE);
}
private void hideEmptyView() {
recyclerView.setVisibility(View.VISIBLE);
emptyView.setVisibility(View.GONE);
}
@Subscribe
public void onEmptyPhotos(MyPhotosEmptyEvent event) {
Log.d(TAG, "list is empty");
showEmptyView();
}
@Override
public void onItemClick(View view, Photo photo) {
//@TODO do some action
}
}
public class PhotoTouchHelper extends ItemTouchHelper.SimpleCallback {
private PhotoAdapter mAdapter;
private RecyclerView mRecyclerView;
public GuideTouchHelper(PhotoAdapter adapter, RecyclerView recyclerView){
super(ItemTouchHelper.UP | ItemTouchHelper.DOWN, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT);
this.mAdapter = adapter;
mRecyclerView = recyclerView;
}
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
return true;
}
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
mAdapter.onItemRemove(viewHolder, mRecyclerView);
}
}
@kingofswing
Copy link

what's this "GuideTouchHelper"?

@noblesilence
Copy link

Thank you so much for the code. It's very helpful. I have one question, is PhotoRemoveService left for our own implementation?

@YvesBill
Copy link

YvesBill commented Mar 17, 2017

int mAdapterPosition = viewHolder.getAdapterPosition(); return always -1. I've used the previous int istead. final int adapterPosition = viewHolder.getAdapterPosition();

So, my code is:
.... public void onClick(View view) { productsList.add(adapterPosition, mPhoto); notifyItemInserted(adapterPosition); recyclerView.scrollToPosition(adapterPosition); productsRem.remove(mPhoto); }

The UNDO function now is fine

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment