Better drag and drop for playlist detail activity

This commit is contained in:
Karim Abou Zeid 2015-12-27 19:59:26 +01:00
commit e2a9c363cc
2 changed files with 101 additions and 24 deletions

View file

@ -7,11 +7,16 @@ import android.support.v7.app.AppCompatActivity;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import com.h6ah4i.android.widget.advrecyclerview.draggable.DraggableItemAdapter;
import com.h6ah4i.android.widget.advrecyclerview.draggable.DraggableItemViewHolder;
import com.h6ah4i.android.widget.advrecyclerview.draggable.ItemDraggableRange;
import com.h6ah4i.android.widget.advrecyclerview.draggable.annotation.DraggableItemStateFlags;
import com.kabouzeid.gramophone.R; import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.dialogs.RemoveFromPlaylistDialog; import com.kabouzeid.gramophone.dialogs.RemoveFromPlaylistDialog;
import com.kabouzeid.gramophone.interfaces.CabHolder; import com.kabouzeid.gramophone.interfaces.CabHolder;
import com.kabouzeid.gramophone.model.PlaylistSong; import com.kabouzeid.gramophone.model.PlaylistSong;
import com.kabouzeid.gramophone.model.Song; import com.kabouzeid.gramophone.model.Song;
import com.kabouzeid.gramophone.util.ViewUtil;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -21,13 +26,16 @@ import java.util.List;
* @author Karim Abou Zeid (kabouzeid) * @author Karim Abou Zeid (kabouzeid)
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public class PlaylistSongAdapter extends SongAdapter { public class PlaylistSongAdapter extends SongAdapter implements DraggableItemAdapter<PlaylistSongAdapter.ViewHolder> {
public static final String TAG = PlaylistSongAdapter.class.getSimpleName(); public static final String TAG = PlaylistSongAdapter.class.getSimpleName();
public PlaylistSongAdapter(@NonNull AppCompatActivity activity, @NonNull ArrayList<PlaylistSong> dataSet, @LayoutRes int itemLayoutRes, boolean usePalette, @Nullable CabHolder cabHolder) { private OnMoveItemListener onMoveItemListener;
public PlaylistSongAdapter(@NonNull AppCompatActivity activity, @NonNull ArrayList<PlaylistSong> dataSet, @LayoutRes int itemLayoutRes, boolean usePalette, @Nullable CabHolder cabHolder, @Nullable OnMoveItemListener onMoveItemListener) {
super(activity, (ArrayList<Song>) (List) dataSet, itemLayoutRes, usePalette, cabHolder); super(activity, (ArrayList<Song>) (List) dataSet, itemLayoutRes, usePalette, cabHolder);
overrideMultiSelectMenuRes(R.menu.menu_playlists_songs_selection); overrideMultiSelectMenuRes(R.menu.menu_playlists_songs_selection);
this.onMoveItemListener = onMoveItemListener;
} }
@Override @Override
@ -44,12 +52,39 @@ public class PlaylistSongAdapter extends SongAdapter {
} }
} }
public class ViewHolder extends SongAdapter.ViewHolder { @Override
public boolean onCheckCanStartDrag(ViewHolder holder, int position, int x, int y) {
return onMoveItemListener != null && ViewUtil.hitTest(holder.dragView, x, y);
}
@Override
public ItemDraggableRange onGetItemDraggableRange(ViewHolder holder, int position) {
return null;
}
@Override
public void onMoveItem(int fromPosition, int toPosition) {
if (onMoveItemListener != null && fromPosition != toPosition) {
onMoveItemListener.onMoveItem(fromPosition, toPosition);
}
}
public interface OnMoveItemListener {
void onMoveItem(int fromPosition, int toPosition);
}
public class ViewHolder extends SongAdapter.ViewHolder implements DraggableItemViewHolder {
@DraggableItemStateFlags
private int mDragStateFlags;
public ViewHolder(@NonNull View itemView) { public ViewHolder(@NonNull View itemView) {
super(itemView); super(itemView);
if (dragView != null) { if (dragView != null) {
dragView.setVisibility(View.VISIBLE); if (onMoveItemListener != null) {
dragView.setVisibility(View.VISIBLE);
} else {
dragView.setVisibility(View.GONE);
}
} }
} }
@ -67,5 +102,16 @@ public class PlaylistSongAdapter extends SongAdapter {
} }
return super.onSongMenuItemClick(item); return super.onSongMenuItemClick(item);
} }
@Override
public void setDragStateFlags(@DraggableItemStateFlags int flags) {
mDragStateFlags = flags;
}
@Override
@DraggableItemStateFlags
public int getDragStateFlags() {
return mDragStateFlags;
}
} }
} }

View file

@ -2,7 +2,7 @@ package com.kabouzeid.gramophone.ui.activities;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar; import android.support.v7.widget.Toolbar;
import android.view.Menu; import android.view.Menu;
@ -11,6 +11,10 @@ import android.view.View;
import android.widget.TextView; import android.widget.TextView;
import com.afollestad.materialcab.MaterialCab; import com.afollestad.materialcab.MaterialCab;
import com.h6ah4i.android.widget.advrecyclerview.animator.GeneralItemAnimator;
import com.h6ah4i.android.widget.advrecyclerview.animator.RefactoredDefaultItemAnimator;
import com.h6ah4i.android.widget.advrecyclerview.draggable.RecyclerViewDragDropManager;
import com.h6ah4i.android.widget.advrecyclerview.utils.WrapperAdapterUtils;
import com.kabouzeid.gramophone.R; import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.adapter.song.PlaylistSongAdapter; import com.kabouzeid.gramophone.adapter.song.PlaylistSongAdapter;
import com.kabouzeid.gramophone.adapter.song.SmartPlaylistSongAdapter; import com.kabouzeid.gramophone.adapter.song.SmartPlaylistSongAdapter;
@ -19,7 +23,6 @@ import com.kabouzeid.gramophone.dialogs.SleepTimerDialog;
import com.kabouzeid.gramophone.helper.MusicPlayerRemote; import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
import com.kabouzeid.gramophone.interfaces.CabHolder; import com.kabouzeid.gramophone.interfaces.CabHolder;
import com.kabouzeid.gramophone.loader.PlaylistSongLoader; import com.kabouzeid.gramophone.loader.PlaylistSongLoader;
import com.kabouzeid.gramophone.misc.DragSortRecycler;
import com.kabouzeid.gramophone.model.Playlist; import com.kabouzeid.gramophone.model.Playlist;
import com.kabouzeid.gramophone.model.PlaylistSong; import com.kabouzeid.gramophone.model.PlaylistSong;
import com.kabouzeid.gramophone.model.Song; import com.kabouzeid.gramophone.model.Song;
@ -54,6 +57,9 @@ public class PlaylistDetailActivity extends AbsSlidingMusicPanelActivity impleme
private MaterialCab cab; private MaterialCab cab;
private SongAdapter adapter; private SongAdapter adapter;
private RecyclerView.Adapter wrappedAdapter;
private RecyclerViewDragDropManager recyclerViewDragDropManager;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@ -79,33 +85,30 @@ public class PlaylistDetailActivity extends AbsSlidingMusicPanelActivity impleme
} }
private void setUpRecyclerView() { private void setUpRecyclerView() {
recyclerView.setLayoutManager(new GridLayoutManager(this, 1)); recyclerView.setLayoutManager(new LinearLayoutManager(this));
if (playlist instanceof AbsSmartPlaylist) { if (playlist instanceof AbsSmartPlaylist) {
adapter = new SmartPlaylistSongAdapter(this, loadSmartPlaylistDataSet(), R.layout.item_list, false, this); adapter = new SmartPlaylistSongAdapter(this, loadSmartPlaylistDataSet(), R.layout.item_list, false, this);
recyclerView.setAdapter(adapter);
} else { } else {
adapter = new PlaylistSongAdapter(this, loadPlaylistDataSet(), R.layout.item_list, false, this); recyclerViewDragDropManager = new RecyclerViewDragDropManager();
final GeneralItemAnimator animator = new RefactoredDefaultItemAnimator();
DragSortRecycler dragSortRecycler = new DragSortRecycler(); adapter = new PlaylistSongAdapter(this, loadPlaylistDataSet(), R.layout.item_list, false, this, new PlaylistSongAdapter.OnMoveItemListener() {
dragSortRecycler.setViewHandleId(R.id.drag_view);
dragSortRecycler.setOnItemMovedListener(new DragSortRecycler.OnItemMovedListener() {
@Override @Override
public void onItemMoved(int from, int to) { public void onMoveItem(int fromPosition, int toPosition) {
if (from == to) return; if (PlaylistsUtil.moveItem(PlaylistDetailActivity.this, playlist.id, fromPosition, toPosition)) {
Song song = adapter.getDataSet().remove(fromPosition);
if (PlaylistsUtil.moveItem(PlaylistDetailActivity.this, playlist.id, from, to)) { adapter.getDataSet().add(toPosition, song);
Song song = adapter.getDataSet().remove(from); adapter.notifyItemMoved(fromPosition, toPosition);
adapter.getDataSet().add(to, song);
adapter.notifyItemMoved(from, to);
} }
} }
}); });
wrappedAdapter = recyclerViewDragDropManager.createWrappedAdapter(adapter);
recyclerView.addItemDecoration(dragSortRecycler); recyclerView.setAdapter(wrappedAdapter);
recyclerView.addOnItemTouchListener(dragSortRecycler); recyclerView.setItemAnimator(animator);
recyclerView.addOnScrollListener(dragSortRecycler.getScrollListener());
recyclerView.setItemAnimator(null); recyclerViewDragDropManager.attachRecyclerView(recyclerView);
} }
recyclerView.setAdapter(adapter);
adapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() { adapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
@Override @Override
@ -211,4 +214,32 @@ public class PlaylistDetailActivity extends AbsSlidingMusicPanelActivity impleme
adapter.getItemCount() == 0 ? View.VISIBLE : View.GONE adapter.getItemCount() == 0 ? View.VISIBLE : View.GONE
); );
} }
@Override
public void onPause() {
recyclerViewDragDropManager.cancelDrag();
super.onPause();
}
@Override
protected void onDestroy() {
if (recyclerViewDragDropManager != null) {
recyclerViewDragDropManager.release();
recyclerViewDragDropManager = null;
}
if (recyclerView != null) {
recyclerView.setItemAnimator(null);
recyclerView.setAdapter(null);
recyclerView = null;
}
if (wrappedAdapter != null) {
WrapperAdapterUtils.releaseAll(wrappedAdapter);
wrappedAdapter = null;
}
adapter = null;
super.onDestroy();
}
} }