Commit 450b0e10 authored by Nicolas Pomepuy's avatar Nicolas Pomepuy Committed by Geoffrey Métais

Allow reorder and swipe to delete on a playlist

parent b16517b1
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/ic_move_media_normal" android:state_focused="true" android:state_pressed="true"/>
<item android:drawable="@drawable/ic_move_media_pressed" android:state_focused="true"/>
<item android:drawable="@drawable/ic_move_media_pressed" android:state_pressed="true"/>
<item android:drawable="@drawable/ic_move_media_normal"/>
</selector>
\ No newline at end of file
......@@ -44,13 +44,25 @@
android:onClick="@{holder::onClick}"
android:onLongClick="@{holder::onLongClick}">
<!-- Image loading is handled by org.videolan.vlc.gui.helpers.ImageLoader.loadImage() -->
<ImageView
android:id="@+id/item_move"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:contentDescription="@string/more_actions"
android:scaleType="center"
android:src="@drawable/ic_move_media"
android:visibility="@{holder.canBeReordered ? View.VISIBLE : View.GONE, default=gone}"
vlc:onTouchListener="@{holder.onTouchListener}"
vlc:layout_constraintBottom_toBottomOf="@+id/subtitle"
vlc:layout_constraintStart_toStartOf="parent"
vlc:layout_constraintTop_toTopOf="@+id/title" />
<ImageView
android:id="@+id/media_cover"
android:layout_width="0dp"
android:layout_height="@dimen/audio_browser_item_size"
android:layout_gravity="center"
android:layout_width="0dp"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
......@@ -59,9 +71,10 @@
android:visibility="@{(item.getItemType() &amp; (MediaLibraryItem.TYPE_ALBUM|MediaLibraryItem.TYPE_ARTIST|MediaLibraryItem.TYPE_MEDIA)) != 0 ? View.VISIBLE : View.GONE, default=gone}"
vlc:layout_constraintBottom_toBottomOf="parent"
vlc:layout_constraintDimensionRatio="1"
vlc:layout_constraintStart_toStartOf="parent"
vlc:layout_constraintTop_toTopOf="parent"
vlc:media="@{item}" />
vlc:layout_constraintStart_toEndOf="@id/item_move"
android:layout_gravity="center"
vlc:media="@{item}"/>
<!-- TextView must be set to singleLine
......
......@@ -47,7 +47,6 @@
<attr name="ic_previous" format="reference" />
<attr name="ic_next" format="reference" />
<attr name="ic_close" format="reference" />
<attr name="ic_move_media" format="reference" />
<attr name="ic_save" format="reference" />
<attr name="ic_trash" format="reference" />
<attr name="ic_reset" format="reference" />
......
......@@ -678,6 +678,7 @@
<string name="video_save_clone_mode">Automatically activate clone mode?</string>
<string name="video_remote_enable">Switch to remote control mode</string>
<string name="video_remote_disable">Duplicate screen</string>
<string name="removed_from_playlist_anonymous">Item(s) removed from playlist</string>
<string name="welcome_title">Welcome to VLC!</string>
<string name="welcome_subtitle">The free and open source multimedia player</string>
<string name="permission_media">VLC needs your permission to access media on your device</string>
......
......@@ -67,7 +67,6 @@
<item name="ic_next">@drawable/ic_next</item>
<item name="ic_close">@drawable/ic_close</item>
<item name="ic_save">@drawable/ic_save</item>
<item name="ic_move_media">@drawable/ic_move_media</item>
<item name="ic_trash">@drawable/ic_trash</item>
<item name="ic_reset">@drawable/ic_reset</item>
<item name="shadow_top_9patch">@drawable/shadow_top</item>
......@@ -172,7 +171,6 @@
<item name="ic_next">@drawable/ic_next_w</item>
<item name="ic_close">@drawable/ic_close_w</item>
<item name="ic_save">@drawable/ic_save_w</item>
<item name="ic_move_media">@drawable/ic_move_media_w</item>
<item name="ic_trash">@drawable/ic_trash_w</item>
<item name="ic_reset">@drawable/ic_reset_w</item>
<item name="shadow_top_9patch">@drawable/shadow_top_dark</item>
......
......@@ -259,6 +259,21 @@ public class HistoryFragment extends MediaBrowserFragment<HistoryModel> implemen
@Override
public void onCtxClick(View v, int position, MediaLibraryItem item) {}
@Override
public void onRemove(int position, @NotNull MediaLibraryItem item) {
}
@Override
public void onMove(int position, @NotNull MediaLibraryItem item) {
}
@Override
public void onStartDrag(@NotNull RecyclerView.ViewHolder viewHolder) {
}
@Override
public void onUpdateFinished(RecyclerView.Adapter adapter) {
invalidateActionMode();
......
......@@ -31,6 +31,7 @@ import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuItem;
......@@ -44,6 +45,7 @@ import org.videolan.medialibrary.Medialibrary;
import org.videolan.medialibrary.media.MediaLibraryItem;
import org.videolan.medialibrary.media.MediaWrapper;
import org.videolan.medialibrary.media.Playlist;
import org.videolan.vlc.BuildConfig;
import org.videolan.vlc.R;
import org.videolan.vlc.VLCApplication;
import org.videolan.vlc.databinding.PlaylistActivityBinding;
......@@ -54,6 +56,7 @@ import org.videolan.vlc.gui.dialogs.CtxActionReceiver;
import org.videolan.vlc.gui.dialogs.SavePlaylistDialog;
import org.videolan.vlc.gui.helpers.AudioUtil;
import org.videolan.vlc.gui.helpers.FloatingActionButtonBehavior;
import org.videolan.vlc.gui.helpers.SwipeDragItemTouchHelperCallback;
import org.videolan.vlc.gui.helpers.UiTools;
import org.videolan.vlc.interfaces.IEventsHandler;
import org.videolan.vlc.media.MediaUtils;
......@@ -68,8 +71,10 @@ import org.videolan.vlc.viewmodels.paged.PagedTracksModel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import androidx.annotation.Nullable;
import androidx.appcompat.view.ActionMode;
......@@ -78,6 +83,7 @@ import androidx.databinding.DataBindingUtil;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;
import androidx.paging.PagedList;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import kotlinx.coroutines.Job;
......@@ -85,7 +91,7 @@ import kotlinx.coroutines.Job;
public class PlaylistActivity extends AudioPlayerContainerActivity implements IEventsHandler, ActionMode.Callback, View.OnClickListener, CtxActionReceiver {
public final static String TAG = "VLC/PlaylistActivity";
public final static String TAG_FAB_VISIBILITY= "FAB";
public final static String TAG_FAB_VISIBILITY = "FAB";
private AudioBrowserAdapter mAdapter;
private MediaLibraryItem mPlaylist;
......@@ -94,6 +100,7 @@ public class PlaylistActivity extends AudioPlayerContainerActivity implements IE
private ActionMode mActionMode;
private boolean mIsPlaylist;
private PagedTracksModel tracksModel;
private ItemTouchHelper mItemTouchHelper;
@Override
public void onCreate(final Bundle savedInstanceState) {
......@@ -112,7 +119,7 @@ public class PlaylistActivity extends AudioPlayerContainerActivity implements IE
mIsPlaylist = mPlaylist.getItemType() == MediaLibraryItem.TYPE_PLAYLIST;
mBinding.setPlaylist(mPlaylist);
tracksModel = ViewModelProviders.of(this, new PagedTracksModel.Factory(this, mPlaylist)).get(PagedTracksModel.class);
((MLPagedModel)tracksModel).getPagedList().observe(this, new Observer<PagedList<MediaLibraryItem>>() {
((MLPagedModel) tracksModel).getPagedList().observe(this, new Observer<PagedList<MediaLibraryItem>>() {
@Override
public void onChanged(@Nullable PagedList<MediaLibraryItem> tracks) {
if (tracks != null) {
......@@ -122,6 +129,8 @@ public class PlaylistActivity extends AudioPlayerContainerActivity implements IE
}
});
mAdapter = new AudioBrowserAdapter(MediaLibraryItem.TYPE_MEDIA, this);
mItemTouchHelper = new ItemTouchHelper(new SwipeDragItemTouchHelperCallback(mAdapter));
mItemTouchHelper.attachToRecyclerView(mBinding.songs);
mBinding.songs.setLayoutManager(new LinearLayoutManager(this));
mBinding.songs.setAdapter(mAdapter);
......@@ -206,11 +215,31 @@ public class PlaylistActivity extends AudioPlayerContainerActivity implements IE
@Override
public void onCtxClick(View anchor, final int position, final MediaLibraryItem mediaItem) {
if (mActionMode == null) ContextSheetKt.showContext(this, this, position, mediaItem.getTitle(), Constants.CTX_PLAYLIST_ITEM_FLAGS);
if (mActionMode == null)
ContextSheetKt.showContext(this, this, position, mediaItem.getTitle(), Constants.CTX_PLAYLIST_ITEM_FLAGS);
}
@Override
public void onUpdateFinished(RecyclerView.Adapter adapter) {}
public void onUpdateFinished(RecyclerView.Adapter adapter) {
}
@Override
public void onRemove(int position, @NotNull final MediaLibraryItem item) {
ArrayList<MediaWrapper> tracks = new ArrayList<MediaWrapper>(Arrays.asList(item.getTracks()));
removeFromPlaylist(tracks);
}
@Override
public void onMove(int position, @NotNull MediaLibraryItem item) {
if (BuildConfig.DEBUG) Log.d(TAG, "Moving item: " + item.getId() + " to " + (position + 1));
((Playlist) mPlaylist).move(item.getId(), position + 1);
}
@Override
public void onStartDrag(@NotNull RecyclerView.ViewHolder viewHolder) {
mItemTouchHelper.startDrag(viewHolder);
}
@Override
protected void onPlayerStateChanged(View bottomSheet, int newState) {
......@@ -321,7 +350,7 @@ public class PlaylistActivity extends AudioPlayerContainerActivity implements IE
if (position >= mAdapter.getItemCount()) return;
final MediaWrapper media = (MediaWrapper) mAdapter.getItem(position);
if (media == null) return;
switch (option){
switch (option) {
case Constants.CTX_INFORMATION:
showInfoDialog(media);
break;
......@@ -379,7 +408,8 @@ public class PlaylistActivity extends AudioPlayerContainerActivity implements IE
String parentPath = FileUtils.getParent(path);
if (FileUtils.deleteFile(path) && media.getId() > 0L && !foldersToReload.contains(parentPath)) {
foldersToReload.add(parentPath);
} else UiTools.snacker(mBinding.getRoot(), getString(R.string.msg_delete_failed, media.getTitle()));
} else
UiTools.snacker(mBinding.getRoot(), getString(R.string.msg_delete_failed, media.getTitle()));
}
for (String folder : foldersToReload) mMediaLibrary.reload(folder);
}
......@@ -391,11 +421,26 @@ public class PlaylistActivity extends AudioPlayerContainerActivity implements IE
MediaUtils.INSTANCE.playTracks(this, mPlaylist, 0);
}
private void removeFromPlaylist(final List<MediaWrapper> list){
UiTools.snackerConfirm(mBinding.getRoot(), getString(R.string.confirm_remove_from_playlist_anonymous), new Runnable() {
private void removeFromPlaylist(final List<MediaWrapper> list) {
final HashMap<Integer, Long> itemsRemoved = new HashMap<>();
final Playlist playlist = (Playlist) this.mPlaylist;
for (MediaLibraryItem mediaItem : list) {
for (int i = 0; i < playlist.getTracks().length; i++) {
if (playlist.getTracks()[i].getId() == mediaItem.getId()) {
itemsRemoved.put(i + 1, mediaItem.getId());
}
}
playlist.remove(mediaItem.getId());
}
UiTools.snackerWithCancel(mBinding.getRoot(), getString(R.string.removed_from_playlist_anonymous), null, new Runnable() {
@Override
public void run() {
for (MediaLibraryItem mediaItem : list) ((Playlist) mPlaylist).remove(mediaItem.getId());
for (Map.Entry<Integer, Long> removedItem : itemsRemoved.entrySet()) {
playlist.add(removedItem.getValue(), removedItem.getKey());
}
}
});
}
......
......@@ -111,6 +111,14 @@ class PlaylistFragment : BaseAudioBrowser(), Observer<PagedList<MediaLibraryItem
} else super.onClick(v, position, item)
}
override fun onRemove(position: Int, item: MediaLibraryItem) {
}
override fun onMove(position: Int, item: MediaLibraryItem) {
}
override fun onRefresh() {
activity?.reloadLibrary()
}
......
......@@ -28,6 +28,7 @@ import android.content.Context;
import android.graphics.drawable.BitmapDrawable;
import android.os.Build;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
......@@ -42,6 +43,7 @@ import org.videolan.vlc.gui.helpers.ImageLoaderKt;
import org.videolan.vlc.gui.helpers.SelectorViewHolder;
import org.videolan.vlc.gui.view.FastScroller;
import org.videolan.vlc.interfaces.IEventsHandler;
import org.videolan.vlc.interfaces.SwipeDragHelperAdapter;
import org.videolan.vlc.util.Constants;
import org.videolan.vlc.util.Util;
......@@ -49,6 +51,8 @@ import java.util.List;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.view.MotionEventCompat;
import androidx.databinding.ViewDataBinding;
import androidx.fragment.app.Fragment;
import androidx.paging.PagedList;
import androidx.paging.PagedListAdapter;
......@@ -56,23 +60,25 @@ import androidx.recyclerview.widget.DiffUtil;
import static org.videolan.medialibrary.media.MediaLibraryItem.FLAG_SELECTED;
public class AudioBrowserAdapter extends PagedListAdapter<MediaLibraryItem, AudioBrowserAdapter.MediaItemViewHolder> implements FastScroller.SeparatedAdapter, MultiSelectAdapter<MediaLibraryItem> {
public class AudioBrowserAdapter extends PagedListAdapter<MediaLibraryItem, AudioBrowserAdapter.MediaItemViewHolder> implements FastScroller.SeparatedAdapter, MultiSelectAdapter<MediaLibraryItem>, SwipeDragHelperAdapter {
private static final String TAG = "VLC/AudioBrowserAdapter";
private static final int UPDATE_PAYLOAD = 1;
private final IEventsHandler mIEventsHandler;
private final boolean mCanBeReordered;
private MultiSelectHelper<MediaLibraryItem> multiSelectHelper;
private final int mType;
private final boolean mHasSections;
private final BitmapDrawable mDefaultCover;
public AudioBrowserAdapter(int type, IEventsHandler eventsHandler, boolean sections) {
public AudioBrowserAdapter(int type, IEventsHandler eventsHandler, boolean sections, boolean canBeReordered) {
super(DIFF_CALLBACK);
multiSelectHelper = new MultiSelectHelper<>(this, Constants.UPDATE_SELECTION);
mIEventsHandler = eventsHandler;
mType = type;
mHasSections = sections;
mCanBeReordered = canBeReordered;
Context ctx = null;
if (eventsHandler instanceof Context) ctx = (Context) eventsHandler;
else if (eventsHandler instanceof Fragment) ctx = ((Fragment)eventsHandler).getContext();
......@@ -80,7 +86,7 @@ public class AudioBrowserAdapter extends PagedListAdapter<MediaLibraryItem, Audi
}
public AudioBrowserAdapter(int type, IEventsHandler eventsHandler) {
this(type, eventsHandler, true);
this(type, eventsHandler, true, false);
}
@NonNull
......@@ -99,6 +105,7 @@ public class AudioBrowserAdapter extends PagedListAdapter<MediaLibraryItem, Audi
final boolean isSelected = multiSelectHelper.isSelected(position);
holder.setCoverlay(isSelected);
holder.selectView(isSelected);
holder.setCanBeReordered(mCanBeReordered);
holder.binding.executePendingBindings();
}
......@@ -116,6 +123,7 @@ public class AudioBrowserAdapter extends PagedListAdapter<MediaLibraryItem, Audi
final boolean isSelected = multiSelectHelper.isSelected(position);
holder.setCoverlay(isSelected);
holder.selectView(isSelected);
holder.setCanBeReordered(mCanBeReordered);
}
}
}
......@@ -177,8 +185,27 @@ public class AudioBrowserAdapter extends PagedListAdapter<MediaLibraryItem, Audi
return true;
}
@Override
public void onItemMove(int fromPosition, int toPosition) {
notifyItemMoved(fromPosition, toPosition);
}
@Override
public void onItemMoved(int dragFrom, int dragTo) {
final MediaLibraryItem item = getItem(dragFrom);
mIEventsHandler.onMove(dragTo, item);
}
@Override
public void onItemDismiss(int position) {
final MediaLibraryItem item = getItem(position);
mIEventsHandler.onRemove(position, item);
}
public class MediaItemViewHolder extends SelectorViewHolder<AudioBrowserItemBinding> implements View.OnFocusChangeListener {
int coverlayResource = 0;
public View.OnTouchListener onTouchListener;
private boolean canBeReordered;
@TargetApi(Build.VERSION_CODES.M)
MediaItemViewHolder(AudioBrowserItemBinding binding) {
......@@ -193,6 +220,22 @@ public class AudioBrowserAdapter extends PagedListAdapter<MediaLibraryItem, Audi
return true;
}
});
onTouchListener = new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (!mCanBeReordered) {
return false;
}
if (multiSelectHelper.getSelectionCount() != 0) {
return false;
}
if (MotionEventCompat.getActionMasked(event) == MotionEvent.ACTION_DOWN) {
mIEventsHandler.onStartDrag(MediaItemViewHolder.this);
}
return false;
}
};
}
public void onClick(View v) {
......@@ -231,6 +274,14 @@ public class AudioBrowserAdapter extends PagedListAdapter<MediaLibraryItem, Audi
protected boolean isSelected() {
return multiSelectHelper.isSelected(getLayoutPosition());
}
public void setCanBeReordered(boolean canBeReordered) {
this.canBeReordered = canBeReordered;
}
public boolean getCanBeReordered() {
return canBeReordered;
}
}
private static final DiffUtil.ItemCallback<MediaLibraryItem> DIFF_CALLBACK =
......
......@@ -280,6 +280,21 @@ public abstract class BaseAudioBrowser extends MediaBrowserFragment<MLPagedModel
if (mActionMode == null) ContextSheetKt.showContext(requireActivity(), this, position, item.getTitle(), flags);
}
@Override
public void onRemove(int position, @NotNull MediaLibraryItem item) {
}
@Override
public void onMove(int position, @NotNull MediaLibraryItem item) {
}
@Override
public void onStartDrag(@NotNull RecyclerView.ViewHolder viewHolder) {
}
@Override
public void onUpdateFinished(RecyclerView.Adapter adapter) {
UiTools.updateSortTitles(this);
......
......@@ -25,12 +25,8 @@ package org.videolan.vlc.gui.audio;
import android.annotation.TargetApi;
import android.content.Context;
import androidx.databinding.DataBindingUtil;
import android.os.Build;
import android.os.Message;
import androidx.annotation.MainThread;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
......@@ -52,6 +48,11 @@ import org.videolan.vlc.viewmodels.PlaylistModel;
import java.util.Collections;
import androidx.annotation.MainThread;
import androidx.databinding.DataBindingUtil;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.RecyclerView;
public class PlaylistAdapter extends DiffUtilAdapter<MediaWrapper, PlaylistAdapter.ViewHolder> implements SwipeDragHelperAdapter {
private static final String TAG = "VLC/PlaylistAdapter";
......@@ -142,6 +143,11 @@ public class PlaylistAdapter extends DiffUtilAdapter<MediaWrapper, PlaylistAdapt
mHandler.obtainMessage(PlaylistHandler.ACTION_MOVE, fromPosition, toPosition).sendToTarget();
}
@Override
public void onItemMoved(int dragFrom, int dragTo) {
}
@Override
public void onItemDismiss(final int position) {
final MediaWrapper media = getItem(position);
......
......@@ -435,6 +435,18 @@ abstract class BaseBrowserFragment : MediaBrowserFragment<BrowserModel>(), IRefr
}
}
override fun onRemove(position: Int, item: MediaLibraryItem) {
}
override fun onMove(position: Int, item: MediaLibraryItem) {
}
override fun onStartDrag(viewHolder: RecyclerView.ViewHolder) {
}
override fun onCtxAction(position: Int, option: Int) {
if (adapter.getItem(position) !is MediaWrapper) return
val mw = adapter.getItem(position) as MediaWrapper
......
......@@ -31,6 +31,7 @@ import android.text.TextUtils
import android.view.View
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProviders
import androidx.recyclerview.widget.RecyclerView
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
import org.videolan.medialibrary.media.MediaLibraryItem
......@@ -87,6 +88,18 @@ class FilePickerFragment : FileBrowserFragment() {
}
override fun onRemove(position: Int, item: MediaLibraryItem) {
}
override fun onMove(position: Int, item: MediaLibraryItem) {
}
override fun onStartDrag(viewHolder: RecyclerView.ViewHolder) {
}
private fun pickFile(mw: MediaWrapper) {
val i = Intent(Intent.ACTION_PICK)
i.putExtra(EXTRA_MRL, mw.location)
......
......@@ -39,6 +39,9 @@ import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProviders
import kotlinx.coroutines.*
import androidx.recyclerview.widget.RecyclerView
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.launch
import org.videolan.libvlc.util.AndroidUtil
import org.videolan.medialibrary.interfaces.EntryPointsEventsCb
import org.videolan.medialibrary.media.MediaLibraryItem
......@@ -193,6 +196,18 @@ class StorageBrowserFragment : FileBrowserFragment(), EntryPointsEventsCb, Corou
}
}
override fun onRemove(position: Int, item: MediaLibraryItem) {
}
override fun onMove(position: Int, item: MediaLibraryItem) {
}
override fun onStartDrag(viewHolder: RecyclerView.ViewHolder) {
}
internal fun processEvent(cbp: CheckBox, mrl: String) {
cbp.isEnabled = false
mProcessingFolders.put(mrl, cbp)
......
......@@ -23,34 +23,68 @@
package org.videolan.vlc.gui.helpers;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.ItemTouchHelper;
import org.jetbrains.annotations.NotNull;
import org.videolan.vlc.interfaces.SwipeDragHelperAdapter;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.RecyclerView;
public class SwipeDragItemTouchHelperCallback extends ItemTouchHelper.Callback {
private static final String TAG = SwipeDragItemTouchHelperCallback.class.getSimpleName();
private final SwipeDragHelperAdapter mAdapter;
private int dragFrom;
private int dragTo;
public SwipeDragItemTouchHelperCallback(SwipeDragHelperAdapter mAdapter) {
this.mAdapter = mAdapter;
}
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
public int getMovementFlags(@NotNull RecyclerView recyclerView, @NotNull RecyclerView.ViewHolder viewHolder) {
int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;
return makeMovementFlags(dragFlags, swipeFlags);
}
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
public boolean onMove(@NotNull RecyclerView recyclerView, @NotNull RecyclerView.ViewHolder viewHolder, @NotNull RecyclerView.ViewHolder target) {
mAdapter.onItemMove(viewHolder.getLayoutPosition(), target.getLayoutPosition());
int fromPosition = viewHolder.getLayoutPosition();
int toPosition = target.getLayoutPosition();
if(dragFrom == -1) {
dragFrom = fromPosition;
}
dragTo = toPosition;
return true;
}
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
public boolean isLongPressDragEnabled() {
return false;
}
@Override
public void onMoved(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, int fromPos, @NonNull RecyclerView.ViewHolder target, int toPos, int x, int y) {
super.onMoved(recyclerView, viewHolder, fromPos, target, toPos, x, y);
}
@Override
public void clearView(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
if(dragFrom != -1 && dragTo != -1 && dragFrom != dragTo) {
mAdapter.onItemMoved(dragFrom, dragTo);
}
dragFrom = dragTo = -1;
super.clearView(recyclerView, viewHolder);
}
@Override
public void onSwiped(@NotNull RecyclerView.ViewHolder viewHolder, int direction) {
mAdapter.onItemDismiss(viewHolder.getLayoutPosition());
}
}
......@@ -53,6 +53,7 @@ import android.view.DragAndDropPermissions;
import android.view.DragEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
......@@ -238,6 +239,17 @@ public class UiTools {
}
}
/**
* sets the touch listener for a view
* @param view the view
* @param onTouchListener the listener
*/
@BindingAdapter("touchListener")
public void setTouchListener(View view,View.OnTouchListener onTouchListener){
if (onTouchListener != null)
view.setOnTouchListener(onTouchListener);
}
public static void setViewVisibility(View v, int visibility) {
if (v != null) v.setVisibility(visibility);
}
......
......@@ -414,6 +414,21 @@ public class VideoGridFragment extends MediaBrowserFragment<VideosModel> impleme
ContextSheetKt.showContext(requireActivity(), this, position, item.getTitle(), flags);
}
@Override
public void onRemove(int position, @NotNull MediaLibraryItem item) {
}
@Override
public void onMove(int position, @NotNull MediaLibraryItem item) {
}
@Override
public void onStartDrag(@NotNull RecyclerView.ViewHolder viewHolder) {
}
@Override
public void onUpdateFinished(RecyclerView.Adapter adapter) {
if (!mMediaLibrary.isWorking()) mHandler.sendEmptyMessage(UNSET_REFRESHING);
......
......@@ -10,4 +10,7 @@ interface IEventsHandler {
fun onImageClick(v: View, position: Int, item: MediaLibraryItem)
fun onCtxClick(v: View, position: Int, item: MediaLibraryItem)
fun onUpdateFinished(adapter: RecyclerView.Adapter<*>)