Commit d3256e14 authored by Geoffrey Métais's avatar Geoffrey Métais
Browse files

Refactor Fast Scroller

parent 28562a42
......@@ -127,8 +127,6 @@ public class AudioAlbumsSongsFragment extends BaseAudioBrowser implements SwipeR
final String[] titles = new String[] {getString(R.string.albums), getString(R.string.songs)};
mAlbumsAdapter = new AudioBrowserAdapter(MediaLibraryItem.TYPE_ALBUM, this);
mSongsAdapter = new AudioBrowserAdapter(MediaLibraryItem.TYPE_MEDIA, this);
mAlbumsAdapter.setParentAdapterType(mItem.getItemType());
mSongsAdapter.setParentAdapterType(mItem.getItemType());
mAdapters = new AudioBrowserAdapter[]{mAlbumsAdapter, mSongsAdapter};
songsList.setAdapter(mSongsAdapter);
......
......@@ -40,7 +40,6 @@ import org.videolan.vlc.databinding.AudioBrowserSeparatorBinding;
import org.videolan.vlc.gui.DiffUtilAdapter;
import org.videolan.vlc.gui.helpers.SelectorViewHolder;
import org.videolan.vlc.gui.helpers.UiTools;
import org.videolan.vlc.gui.view.FastScroller;
import org.videolan.vlc.interfaces.IEventsHandler;
import org.videolan.vlc.util.Util;
......@@ -52,16 +51,15 @@ import java.util.List;
import static org.videolan.medialibrary.media.MediaLibraryItem.FLAG_SELECTED;
import static org.videolan.medialibrary.media.MediaLibraryItem.TYPE_PLAYLIST;
public class AudioBrowserAdapter extends DiffUtilAdapter<MediaLibraryItem, AudioBrowserAdapter.ViewHolder> implements FastScroller.SeparatedAdapter {
public class AudioBrowserAdapter extends DiffUtilAdapter<MediaLibraryItem, AudioBrowserAdapter.ViewHolder> {
private static final String TAG = "VLC/AudioBrowserAdapter";
private List<MediaLibraryItem> mOriginalDataSet;
private IEventsHandler mIEventsHandler;
private final IEventsHandler mIEventsHandler;
private final int mType;
private final BitmapDrawable mDefaultCover;
private int mSelectionCount = 0;
private int mType;
private int mParentType = 0;
private BitmapDrawable mDefaultCover;
public AudioBrowserAdapter(int type, IEventsHandler eventsHandler) {
mIEventsHandler = eventsHandler;
......@@ -69,37 +67,23 @@ public class AudioBrowserAdapter extends DiffUtilAdapter<MediaLibraryItem, Audio
mDefaultCover = getIconDrawable();
}
public int getAdapterType() {
return mType;
}
public void setParentAdapterType(int type) {
mParentType = type;
}
public int getParentAdapterType() {
return mParentType;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = (LayoutInflater) parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final LayoutInflater inflater = (LayoutInflater) parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (viewType == MediaLibraryItem.TYPE_DUMMY) {
final AudioBrowserSeparatorBinding binding = AudioBrowserSeparatorBinding.inflate(inflater, parent, false);
return new ViewHolder<>(binding);
} else {
final AudioBrowserItemBinding binding = AudioBrowserItemBinding.inflate(inflater, parent, false);
if (mType == TYPE_PLAYLIST) // Hide context button for playlist in save playlist dialog
binding.itemMore.setVisibility(View.GONE);
// Hide context button for playlist in save playlist dialog
if (mType == TYPE_PLAYLIST) binding.itemMore.setVisibility(View.GONE);
return new MediaItemViewHolder(binding);
}
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
if (position >= getDataset().size())
return;
if (position >= getDataset().size()) return;
holder.binding.setVariable(BR.item, getDataset().get(position));
if (holder.getType() == MediaLibraryItem.TYPE_MEDIA) {
final boolean isSelected = getDataset().get(position).hasStateFlags(FLAG_SELECTED);
......@@ -110,11 +94,10 @@ public class AudioBrowserAdapter extends DiffUtilAdapter<MediaLibraryItem, Audio
@Override
public void onBindViewHolder(ViewHolder holder, int position, List<Object> payloads) {
if (Util.isListEmpty(payloads))
onBindViewHolder(holder, position);
if (Util.isListEmpty(payloads)) onBindViewHolder(holder, position);
else {
final boolean isSelected = ((MediaLibraryItem)payloads.get(0)).hasStateFlags(FLAG_SELECTED);
MediaItemViewHolder miv = (MediaItemViewHolder) holder;
final MediaItemViewHolder miv = (MediaItemViewHolder) holder;
miv.setCoverlay(isSelected);
miv.selectView(isSelected);
}
......@@ -123,8 +106,7 @@ public class AudioBrowserAdapter extends DiffUtilAdapter<MediaLibraryItem, Audio
@Override
public void onViewRecycled(ViewHolder holder) {
if (mDefaultCover != null)
holder.binding.setVariable(BR.cover, mDefaultCover);
if (mDefaultCover != null) holder.binding.setVariable(BR.cover, mDefaultCover);
}
@Override
......@@ -145,9 +127,8 @@ public class AudioBrowserAdapter extends DiffUtilAdapter<MediaLibraryItem, Audio
}
List<MediaLibraryItem> getMediaItems() {
List<MediaLibraryItem> list = new ArrayList<>();
for (MediaLibraryItem item : getDataset())
if (!(item.getItemType() == MediaLibraryItem.TYPE_DUMMY)) list.add(item);
final List<MediaLibraryItem> list = new ArrayList<>();
for (MediaLibraryItem item : getDataset()) if (!(item.getItemType() == MediaLibraryItem.TYPE_DUMMY)) list.add(item);
return list;
}
......@@ -172,18 +153,6 @@ public class AudioBrowserAdapter extends DiffUtilAdapter<MediaLibraryItem, Audio
return getItem(position).getItemType();
}
public boolean hasSections() {
return false;
}
@Override
public String getSectionforPosition(int position) {
// if (mMakeSections)
// for (int i = position; i >= 0; --i)
// if (getDataset().get(i).getItemType() == MediaLibraryItem.TYPE_DUMMY) return getDataset().get(i).getTitle();
return "";
}
@MainThread
public boolean isEmpty() {
return (peekLast().size() == 0);
......@@ -194,14 +163,6 @@ public class AudioBrowserAdapter extends DiffUtilAdapter<MediaLibraryItem, Audio
mOriginalDataSet = null;
}
private List<MediaLibraryItem> removeSections(List<MediaLibraryItem> items) {
List<MediaLibraryItem> newList = new ArrayList<>();
for (MediaLibraryItem item : items)
if (item.getItemType() != MediaLibraryItem.TYPE_DUMMY)
newList.add(item);
return newList;
}
public void remove(final MediaLibraryItem... items) {
final List<MediaLibraryItem> referenceList = peekLast();
if (referenceList.isEmpty()) return;
......@@ -234,9 +195,7 @@ public class AudioBrowserAdapter extends DiffUtilAdapter<MediaLibraryItem, Audio
@MainThread
public List<MediaLibraryItem> getSelection() {
final List<MediaLibraryItem> selection = new LinkedList<>();
for (MediaLibraryItem item : getDataset())
if (item.hasStateFlags(FLAG_SELECTED))
selection.add(item);
for (MediaLibraryItem item : getDataset()) if (item.hasStateFlags(FLAG_SELECTED)) selection.add(item);
return selection;
}
......@@ -332,41 +291,4 @@ public class AudioBrowserAdapter extends DiffUtilAdapter<MediaLibraryItem, Audio
return getItem(getLayoutPosition()).hasStateFlags(FLAG_SELECTED);
}
}
// @Override
// public int getDefaultSort() {
// switch (mParentType) {
// case MediaLibraryItem.TYPE_ARTIST:
// return mType == MediaLibraryItem.TYPE_ALBUM ? MediaLibraryItemComparator.SORT_BY_DATE : MediaLibraryItemComparator.SORT_BY_ALBUM;
// case MediaLibraryItem.TYPE_GENRE:
// return mType == MediaLibraryItem.TYPE_ALBUM ? MediaLibraryItemComparator.SORT_BY_TITLE : MediaLibraryItemComparator.SORT_BY_ALBUM;
// default:
// return MediaLibraryItemComparator.SORT_BY_TITLE;
// }
// }
// @Override
// public int getDefaultDirection() {
// return mParentType == MediaLibraryItem.TYPE_ARTIST ? -1 : 1;
// }
//
// @Override
// protected boolean isSortAllowed(int sort) {
// switch (sort) {
// case MediaLibraryItemComparator.SORT_BY_TITLE:
// return true;
// case MediaLibraryItemComparator.SORT_BY_DATE:
// return mType == MediaLibraryItem.TYPE_ALBUM;
// case MediaLibraryItemComparator.SORT_BY_LENGTH:
// return mType == MediaLibraryItem.TYPE_ALBUM || mType == MediaLibraryItem.TYPE_MEDIA;
// case MediaLibraryItemComparator.SORT_BY_NUMBER:
// return mType == MediaLibraryItem.TYPE_ALBUM || mType == MediaLibraryItem.TYPE_PLAYLIST;
// case MediaLibraryItemComparator.SORT_BY_ALBUM:
// return mParentType != 0 && mType == MediaLibraryItem.TYPE_MEDIA;
// case MediaLibraryItemComparator.SORT_BY_ARTIST:
// return mParentType == MediaLibraryItem.TYPE_GENRE && mType == MediaLibraryItem.TYPE_MEDIA;
// default:
// return false;
// }
// }
}
......@@ -421,7 +421,7 @@ public class AudioBrowserFragment extends BaseAudioBrowser implements SwipeRefre
@Override
public void onTabSelected(TabLayout.Tab tab) {
getActivity().supportInvalidateOptionsMenu();
getActivity().invalidateOptionsMenu();
mFastScroller.setRecyclerView(mLists[tab.getPosition()]);
VLCApplication.getSettings().edit().putInt(Constants.KEY_AUDIO_CURRENT_TAB, tab.getPosition()).apply();
}
......
......@@ -33,7 +33,6 @@ import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.NonNull;
import android.support.v4.view.ViewCompat;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
......@@ -43,13 +42,17 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import org.videolan.medialibrary.media.MediaLibraryItem;
import org.videolan.vlc.R;
import org.videolan.vlc.gui.DiffUtilAdapter;
import org.videolan.vlc.util.WeakHandler;
import java.util.TreeMap;
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public class FastScroller extends LinearLayout {
private static final String TAG = "FastScroller";
private static final int HANDLE_ANIMATION_DURATION = 100;
......@@ -73,11 +76,7 @@ public class FastScroller extends LinearLayout {
private RecyclerView mRecyclerView;
private ImageView handle;
private TextView bubble;
public interface SeparatedAdapter {
boolean hasSections();
String getSectionforPosition(int position);
}
private final TreeMap<Integer, String> sections = new TreeMap<>();
public FastScroller(Context context, AttributeSet attrs) {
super(context, attrs);
......@@ -93,7 +92,7 @@ public class FastScroller extends LinearLayout {
private void initialize(Context context) {
setOrientation(HORIZONTAL);
setClipChildren(false);
LayoutInflater inflater = LayoutInflater.from(context);
final LayoutInflater inflater = LayoutInflater.from(context);
inflater.inflate(R.layout.fastscroller, this);
handle = findViewById(R.id.fastscroller_handle);
bubble = findViewById(R.id.fastscroller_bubble);
......@@ -111,9 +110,9 @@ public class FastScroller extends LinearLayout {
bubble.setPivotY(bubble.getHeight());
scrollListener.onScrolled(mRecyclerView, 0, 0);
bubble.setVisibility(VISIBLE);
Animator growerX = ObjectAnimator.ofFloat(bubble, SCALE_X, 0f, 1f).setDuration(HANDLE_ANIMATION_DURATION);
Animator growerY = ObjectAnimator.ofFloat(bubble, SCALE_Y, 0f, 1f).setDuration(HANDLE_ANIMATION_DURATION);
Animator alpha = ObjectAnimator.ofFloat(bubble, ALPHA, 0f, 1f).setDuration(HANDLE_ANIMATION_DURATION);
final Animator growerX = ObjectAnimator.ofFloat(bubble, SCALE_X, 0f, 1f).setDuration(HANDLE_ANIMATION_DURATION);
final Animator growerY = ObjectAnimator.ofFloat(bubble, SCALE_Y, 0f, 1f).setDuration(HANDLE_ANIMATION_DURATION);
final Animator alpha = ObjectAnimator.ofFloat(bubble, ALPHA, 0f, 1f).setDuration(HANDLE_ANIMATION_DURATION);
animatorSet.playTogether(growerX, growerY, alpha);
animatorSet.start();
}
......@@ -122,9 +121,9 @@ public class FastScroller extends LinearLayout {
mCurrentAnimator = new AnimatorSet();
bubble.setPivotX(bubble.getWidth());
bubble.setPivotY(bubble.getHeight());
Animator shrinkerX = ObjectAnimator.ofFloat(bubble, SCALE_X, 1f, 0f).setDuration(HANDLE_ANIMATION_DURATION);
Animator shrinkerY = ObjectAnimator.ofFloat(bubble, SCALE_Y, 1f, 0f).setDuration(HANDLE_ANIMATION_DURATION);
Animator alpha = ObjectAnimator.ofFloat(bubble, ALPHA, 1f, 0f).setDuration(HANDLE_ANIMATION_DURATION);
final Animator shrinkerX = ObjectAnimator.ofFloat(bubble, SCALE_X, 1f, 0f).setDuration(HANDLE_ANIMATION_DURATION);
final Animator shrinkerY = ObjectAnimator.ofFloat(bubble, SCALE_Y, 1f, 0f).setDuration(HANDLE_ANIMATION_DURATION);
final Animator alpha = ObjectAnimator.ofFloat(bubble, ALPHA, 1f, 0f).setDuration(HANDLE_ANIMATION_DURATION);
mCurrentAnimator.playTogether(shrinkerX, shrinkerY, alpha);
mCurrentAnimator.addListener(new AnimatorListenerAdapter() {
@Override
......@@ -149,20 +148,30 @@ public class FastScroller extends LinearLayout {
private void setPosition(float y) {
final float position = y / mHeight;
final int handleHeight = handle.getHeight();
ViewCompat.setY(handle, getValueInRange(0, mHeight - handleHeight, (int) ((mHeight - handleHeight) * position)));
handle.setY(getValueInRange(0, mHeight - handleHeight, (int) ((mHeight - handleHeight) * position)));
final int bubbleHeight = bubble.getHeight();
ViewCompat.setY(bubble, getValueInRange(0, mHeight - bubbleHeight, (int) ((mHeight - bubbleHeight) * position) - handleHeight));
bubble.setY(getValueInRange(0, mHeight - bubbleHeight, (int) ((mHeight - bubbleHeight) * position) - handleHeight));
}
public void setRecyclerView(RecyclerView recyclerView) {
if (mRecyclerView != null)
mRecyclerView.removeOnScrollListener(scrollListener);
if (mRecyclerView != null) mRecyclerView.removeOnScrollListener(scrollListener);
setVisibility(INVISIBLE);
mItemCount = recyclerView.getAdapter().getItemCount();
this.mRecyclerView = recyclerView;
mRecyclerviewTotalHeight = 0;
prepareSectionsMap();
recyclerView.addOnScrollListener(scrollListener);
mShowBubble = true;//TODO ((SeparatedAdapter)recyclerView.getAdapter()).hasSections();
mShowBubble = !sections.isEmpty();
}
private void prepareSectionsMap() {
sections.clear();
final DiffUtilAdapter adapter = (DiffUtilAdapter) mRecyclerView.getAdapter();
final int count = adapter.getItemCount();
for (int i = 0; i < count; ++i) {
if (adapter.getItemViewType(i) == MediaLibraryItem.TYPE_DUMMY)
sections.put(i, ((MediaLibraryItem) adapter.getItem(i)).getTitle());
}
}
@Override
......@@ -170,12 +179,10 @@ public class FastScroller extends LinearLayout {
if (event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_MOVE) {
mFastScrolling = true;
mCurrentPosition = -1;
if (mCurrentAnimator != null)
mCurrentAnimator.cancel();
if (mCurrentAnimator != null) mCurrentAnimator.cancel();
mHandler.removeMessages(HIDE_SCROLLER);
mHandler.removeMessages(HIDE_HANDLE);
if (mShowBubble && bubble.getVisibility() == GONE)
showBubble();
if (mShowBubble && bubble.getVisibility() == GONE) showBubble();
setRecyclerViewPosition(event.getY());
return true;
} else if (event.getAction() == MotionEvent.ACTION_UP) {
......@@ -190,16 +197,15 @@ public class FastScroller extends LinearLayout {
private void setRecyclerViewPosition(float y) {
if (mRecyclerView != null) {
float proportion;
if (ViewCompat.getY(handle) == 0) {
if (handle.getY() == 0) {
proportion = 0f;
} else if (ViewCompat.getY(handle) + handle.getHeight() >= mHeight - TRACK_SNAP_RANGE) {
} else if (handle.getY() + handle.getHeight() >= mHeight - TRACK_SNAP_RANGE) {
proportion = 1f;
} else {
proportion = y / (float) mHeight;
}
final int targetPos = getValueInRange(0, mItemCount - 1, Math.round(proportion * (float) mItemCount));
if (targetPos == mCurrentPosition)
return;
if (targetPos == mCurrentPosition) return;
mCurrentPosition = targetPos;
mRecyclerView.scrollToPosition(targetPos);
}
......@@ -210,7 +216,7 @@ public class FastScroller extends LinearLayout {
}
private class ScrollListener extends RecyclerView.OnScrollListener {
StringBuilder sb = new StringBuilder();
final StringBuilder sb = new StringBuilder();
@Override
public void onScrolled(RecyclerView rv, int dx, int dy) {
final float proportion = mRecyclerviewTotalHeight == 0 ? 0f : rv.computeVerticalScrollOffset() / (float) mRecyclerviewTotalHeight;
......@@ -220,15 +226,14 @@ public class FastScroller extends LinearLayout {
int position = mCurrentPosition != -1 ? mCurrentPosition
: ((LinearLayoutManager)mRecyclerView.getLayoutManager()).findFirstCompletelyVisibleItemPosition();
sb.append(' ')
.append(((SeparatedAdapter)mRecyclerView.getAdapter()).getSectionforPosition(position))
.append(sections.floorEntry(position).getValue())
.append(' ');
bubble.setText(sb.toString());
return;
}
if (mRecyclerviewTotalHeight == 0)
mRecyclerviewTotalHeight = mRecyclerView.computeVerticalScrollRange()-mRecyclerView.computeVerticalScrollExtent();
if (FastScroller.this.getVisibility() == INVISIBLE)
mHandler.sendEmptyMessage(SHOW_SCROLLER);
if (FastScroller.this.getVisibility() == INVISIBLE) mHandler.sendEmptyMessage(SHOW_SCROLLER);
}
@Override
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment