[Android] Refactor multi-selection in browsers
Geoffrey Métais
git at videolan.org
Thu Sep 6 16:45:42 CEST 2018
vlc-android | branch: master | Geoffrey Métais <geoffrey.metais at gmail.com> | Thu Sep 6 16:45:11 2018 +0200| [c271b062e702f536eb54f7c843f60dae0df45306] | committer: Geoffrey Métais
Refactor multi-selection in browsers
> https://code.videolan.org/videolan/vlc-android/commit/c271b062e702f536eb54f7c843f60dae0df45306
---
.../vlc/gui/browser/BaseBrowserAdapter.java | 49 +++++++---------------
.../vlc/gui/browser/BaseBrowserFragment.kt | 26 ++++--------
2 files changed, 23 insertions(+), 52 deletions(-)
diff --git a/vlc-android/src/org/videolan/vlc/gui/browser/BaseBrowserAdapter.java b/vlc-android/src/org/videolan/vlc/gui/browser/BaseBrowserAdapter.java
index 2ab011170..d529396d2 100644
--- a/vlc-android/src/org/videolan/vlc/gui/browser/BaseBrowserAdapter.java
+++ b/vlc-android/src/org/videolan/vlc/gui/browser/BaseBrowserAdapter.java
@@ -37,6 +37,8 @@ import org.videolan.libvlc.util.AndroidUtil;
import org.videolan.medialibrary.media.MediaLibraryItem;
import org.videolan.medialibrary.media.MediaWrapper;
import org.videolan.medialibrary.media.Storage;
+import org.videolan.tools.MultiSelectAdapter;
+import org.videolan.tools.MultiSelectHelper;
import org.videolan.vlc.R;
import org.videolan.vlc.VLCApplication;
import org.videolan.vlc.databinding.BrowserItemBinding;
@@ -44,6 +46,7 @@ import org.videolan.vlc.databinding.BrowserItemSeparatorBinding;
import org.videolan.vlc.gui.DiffUtilAdapter;
import org.videolan.vlc.gui.helpers.SelectorViewHolder;
import org.videolan.vlc.util.AndroidDevices;
+import org.videolan.vlc.util.Constants;
import java.util.ArrayList;
import java.util.List;
@@ -52,11 +55,13 @@ import static org.videolan.medialibrary.media.MediaLibraryItem.FLAG_SELECTED;
import static org.videolan.medialibrary.media.MediaLibraryItem.TYPE_MEDIA;
import static org.videolan.medialibrary.media.MediaLibraryItem.TYPE_STORAGE;
-public class BaseBrowserAdapter extends DiffUtilAdapter<MediaLibraryItem, BaseBrowserAdapter.ViewHolder> {
+public class BaseBrowserAdapter extends DiffUtilAdapter<MediaLibraryItem, BaseBrowserAdapter.ViewHolder> implements MultiSelectAdapter<MediaLibraryItem> {
protected static final String TAG = "VLC/BaseBrowserAdapter";
private static int FOLDER_RES_ID = R.drawable.ic_menu_folder;
+ private MultiSelectHelper<MediaLibraryItem> multiSelectHelper;
+
private static class Images {
private static final BitmapDrawable IMAGE_FOLDER = new BitmapDrawable(VLCApplication.getAppResources(), BitmapFactory.decodeResource(VLCApplication.getAppResources(), FOLDER_RES_ID));
private static final BitmapDrawable IMAGE_AUDIO = new BitmapDrawable(VLCApplication.getAppResources(), BitmapFactory.decodeResource(VLCApplication.getAppResources(), R.drawable.ic_browser_audio_normal));
@@ -69,11 +74,12 @@ public class BaseBrowserAdapter extends DiffUtilAdapter<MediaLibraryItem, BaseBr
private static final BitmapDrawable IMAGE_QA_DOWNLOAD = new BitmapDrawable(VLCApplication.getAppResources(), BitmapFactory.decodeResource(VLCApplication.getAppResources(), R.drawable.ic_browser_download_normal));
}
protected final BaseBrowserFragment fragment;
- private int mMediaCount = 0, mSelectionCount = 0;
+ private int mMediaCount = 0;
private final boolean mNetworkRoot, mSpecialIcons;
BaseBrowserAdapter(BaseBrowserFragment fragment) {
this.fragment = fragment;
+ multiSelectHelper = new MultiSelectHelper<>(this, Constants.UPDATE_SELECTION);
final boolean root = fragment.isRootDirectory();
final boolean fileBrowser = fragment instanceof FileBrowserFragment;
final boolean filesRoot = root && fileBrowser;
@@ -108,8 +114,10 @@ public class BaseBrowserAdapter extends DiffUtilAdapter<MediaLibraryItem, BaseBr
else if (payloads.get(0) instanceof CharSequence){
((MediaViewHolder) holder).binding.text.setVisibility(View.VISIBLE);
((MediaViewHolder) holder).binding.text.setText((CharSequence) payloads.get(0));
- } else if (payloads.get(0) instanceof MediaWrapper)
- holder.selectView(((MediaWrapper)payloads.get(0)).hasStateFlags(FLAG_SELECTED));
+ } else if (payloads.get(0) instanceof Integer) {
+ final int value = (Integer) payloads.get(0);
+ if (value == Constants.UPDATE_SELECTION) holder.selectView(multiSelectHelper.isSelected(position));
+ }
}
private void onBindMediaViewHolder(final MediaViewHolder vh, int position) {
@@ -121,7 +129,7 @@ public class BaseBrowserAdapter extends DiffUtilAdapter<MediaLibraryItem, BaseBr
&& !"otg".equals(media.getUri().getScheme()));
if (mNetworkRoot) vh.binding.setProtocol(getProtocol(media));
vh.binding.setCover(getIcon(media, mSpecialIcons));
- vh.selectView(media.hasStateFlags(FLAG_SELECTED));
+ vh.selectView(multiSelectHelper.isSelected(position));
}
@Override
@@ -129,8 +137,8 @@ public class BaseBrowserAdapter extends DiffUtilAdapter<MediaLibraryItem, BaseBr
return getDataset().size();
}
- public MediaLibraryItem get(int position) {
- return getDataset().get(position);
+ public MultiSelectHelper<MediaLibraryItem> getMultiSelectHelper() {
+ return multiSelectHelper;
}
public abstract class ViewHolder<T extends ViewDataBinding> extends SelectorViewHolder<T> {
@@ -207,8 +215,7 @@ public class BaseBrowserAdapter extends DiffUtilAdapter<MediaLibraryItem, BaseBr
@Override
protected boolean isSelected() {
- final MediaLibraryItem item = getItem(getLayoutPosition());
- return item != null && item.hasStateFlags(FLAG_SELECTED);
+ return multiSelectHelper.isSelected(getLayoutPosition());
}
}
@@ -281,30 +288,6 @@ public class BaseBrowserAdapter extends DiffUtilAdapter<MediaLibraryItem, BaseBr
protected void checkBoxAction(View v, String mrl){}
- List<MediaWrapper> getSelection() {
- List<MediaWrapper> selection = new ArrayList<>();
- for (MediaLibraryItem item : getDataset()) {
- if (item.hasStateFlags(FLAG_SELECTED))
- selection.add((MediaWrapper) item);
- }
- return selection;
- }
-
- @MainThread
- int getSelectionCount() {
- return mSelectionCount;
- }
-
- @MainThread
- void resetSelectionCount() {
- mSelectionCount = 0;
- }
-
- @MainThread
- void updateSelectionCount(boolean selected) {
- mSelectionCount += selected ? 1 : -1;
- }
-
@SuppressWarnings("unchecked")
@Override
protected List<MediaLibraryItem> prepareList(List<? extends MediaLibraryItem> list) {
diff --git a/vlc-android/src/org/videolan/vlc/gui/browser/BaseBrowserFragment.kt b/vlc-android/src/org/videolan/vlc/gui/browser/BaseBrowserFragment.kt
index 035b77752..486279c90 100644
--- a/vlc-android/src/org/videolan/vlc/gui/browser/BaseBrowserFragment.kt
+++ b/vlc-android/src/org/videolan/vlc/gui/browser/BaseBrowserFragment.kt
@@ -318,21 +318,21 @@ abstract class BaseBrowserFragment : MediaBrowserFragment<BrowserModel>(), IRefr
}
override fun onPrepareActionMode(mode: ActionMode, menu: Menu): Boolean {
- val count = adapter.selectionCount
+ val count = adapter.multiSelectHelper.getSelectionCount()
if (count == 0) {
stopActionMode()
return false
}
val single = this is FileBrowserFragment && count == 1
- val selection = if (single) adapter.selection else null
- val type = if (!Util.isListEmpty(selection)) selection!![0].type else -1
+ val selection = if (single) adapter.multiSelectHelper.getSelection() else null
+ val type = if (!Util.isListEmpty(selection)) (selection!![0] as MediaWrapper).type else -1
menu.findItem(R.id.action_mode_file_info).isVisible = single && (type == MediaWrapper.TYPE_AUDIO || type == MediaWrapper.TYPE_VIDEO)
menu.findItem(R.id.action_mode_file_append).isVisible = PlaylistManager.hasMedia()
return true
}
override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean {
- val list = adapter.selection
+ val list = adapter.multiSelectHelper.getSelection() as? List<MediaWrapper> ?: return false
if (!list.isEmpty()) {
when (item.itemId) {
R.id.action_mode_file_play -> MediaUtils.openList(activity, list, 0)
@@ -351,15 +351,7 @@ abstract class BaseBrowserFragment : MediaBrowserFragment<BrowserModel>(), IRefr
override fun onDestroyActionMode(mode: ActionMode?) {
mActionMode = null
- var index = -1
- for (media in adapter.all) {
- ++index
- if (media.hasStateFlags(MediaLibraryItem.FLAG_SELECTED)) {
- media.removeStateFlags(MediaLibraryItem.FLAG_SELECTED)
- adapter.notifyItemChanged(index, media)
- }
- }
- adapter.resetSelectionCount()
+ adapter.multiSelectHelper.clearSelection()
}
override fun onOptionsItemSelected(item: MenuItem?): Boolean {
@@ -391,9 +383,7 @@ abstract class BaseBrowserFragment : MediaBrowserFragment<BrowserModel>(), IRefr
if (mediaWrapper.type == MediaWrapper.TYPE_AUDIO ||
mediaWrapper.type == MediaWrapper.TYPE_VIDEO ||
mediaWrapper.type == MediaWrapper.TYPE_DIR) {
- item.toggleStateFlag(MediaLibraryItem.FLAG_SELECTED)
- adapter.updateSelectionCount(mediaWrapper.hasStateFlags(MediaLibraryItem.FLAG_SELECTED))
- adapter.notifyItemChanged(position, item)
+ adapter.multiSelectHelper.toggleSelection(position)
invalidateActionMode()
}
} else {
@@ -410,9 +400,7 @@ abstract class BaseBrowserFragment : MediaBrowserFragment<BrowserModel>(), IRefr
mediaWrapper.type == MediaWrapper.TYPE_VIDEO ||
mediaWrapper.type == MediaWrapper.TYPE_DIR) {
if (mActionMode != null) return false
- item.addStateFlags(MediaLibraryItem.FLAG_SELECTED)
- adapter.updateSelectionCount(mediaWrapper.hasStateFlags(MediaLibraryItem.FLAG_SELECTED))
- adapter.notifyItemChanged(position, item)
+ adapter.multiSelectHelper.toggleSelection(position)
startActionMode()
} else onCtxClick(v, position, item)
return true
More information about the Android
mailing list