Fixed the fastscroller lag on huge lists (e.g. song list) by replacing the old fastscroller with an own implementation.
This commit is contained in:
parent
180bf25069
commit
86587d8f1a
4 changed files with 161 additions and 197 deletions
|
|
@ -8,10 +8,8 @@ import android.support.design.widget.AppBarLayout;
|
||||||
import android.support.design.widget.AppBarLayout.OnOffsetChangedListener;
|
import android.support.design.widget.AppBarLayout.OnOffsetChangedListener;
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.MotionEvent;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.FrameLayout;
|
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.kabouzeid.gramophone.R;
|
import com.kabouzeid.gramophone.R;
|
||||||
|
|
@ -54,13 +52,6 @@ public abstract class AbsMainActivityRecyclerViewFragment extends AbsMainActivit
|
||||||
|
|
||||||
if (fastScroller != null) {
|
if (fastScroller != null) {
|
||||||
fastScroller.setRecyclerView(recyclerView);
|
fastScroller.setRecyclerView(recyclerView);
|
||||||
fastScroller.setPressedHandleColor(getMainActivity().getThemeColorPrimary());
|
|
||||||
fastScroller.setOnHandleTouchListener(new View.OnTouchListener() {
|
|
||||||
@Override
|
|
||||||
public boolean onTouch(View v, MotionEvent event) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getMainActivity().addOnAppBarOffsetChangedListener(this);
|
getMainActivity().addOnAppBarOffsetChangedListener(this);
|
||||||
|
|
@ -91,9 +82,13 @@ public abstract class AbsMainActivityRecyclerViewFragment extends AbsMainActivit
|
||||||
@Override
|
@Override
|
||||||
public void onOffsetChanged(AppBarLayout appBarLayout, int i) {
|
public void onOffsetChanged(AppBarLayout appBarLayout, int i) {
|
||||||
if (fastScroller != null) {
|
if (fastScroller != null) {
|
||||||
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) fastScroller.getLayoutParams();
|
fastScroller.setPadding(
|
||||||
params.setMargins(params.leftMargin, params.topMargin, params.rightMargin, getMainActivity().getTotalAppBarScrollingRange() + i);
|
fastScroller.getPaddingLeft(),
|
||||||
fastScroller.setLayoutParams(params);
|
fastScroller.getPaddingTop(),
|
||||||
|
fastScroller.getPaddingRight(),
|
||||||
|
getMainActivity().getTotalAppBarScrollingRange() + i
|
||||||
|
);
|
||||||
|
fastScroller.updateHandlePosition();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,133 +2,181 @@ package com.kabouzeid.gramophone.views;
|
||||||
|
|
||||||
import android.animation.Animator;
|
import android.animation.Animator;
|
||||||
import android.animation.AnimatorListenerAdapter;
|
import android.animation.AnimatorListenerAdapter;
|
||||||
import android.animation.AnimatorSet;
|
|
||||||
import android.animation.ObjectAnimator;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Color;
|
|
||||||
import android.graphics.drawable.ColorDrawable;
|
import android.graphics.drawable.ColorDrawable;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.graphics.drawable.InsetDrawable;
|
import android.graphics.drawable.InsetDrawable;
|
||||||
import android.graphics.drawable.StateListDrawable;
|
import android.graphics.drawable.StateListDrawable;
|
||||||
import android.support.v4.view.animation.FastOutLinearInInterpolator;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.v4.view.animation.LinearOutSlowInInterpolator;
|
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.view.ViewPropertyAnimator;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
|
|
||||||
|
import com.afollestad.materialdialogs.ThemeSingleton;
|
||||||
import com.kabouzeid.gramophone.R;
|
import com.kabouzeid.gramophone.R;
|
||||||
import com.kabouzeid.gramophone.util.Util;
|
import com.kabouzeid.gramophone.util.Util;
|
||||||
|
|
||||||
/**
|
import static android.support.v7.widget.RecyclerView.OnScrollListener;
|
||||||
* Defines a basic widget that will allow for fast scrolling a RecyclerView using the basic paradigm of
|
|
||||||
* a handle and a bar.
|
|
||||||
*/
|
|
||||||
public class FastScroller extends FrameLayout {
|
public class FastScroller extends FrameLayout {
|
||||||
|
private static final int HANDLE_HIDE_DELAY = 1500;
|
||||||
|
private static final int HANDLE_ANIMATION_DURATION = 300;
|
||||||
|
|
||||||
/**
|
private View handle;
|
||||||
* The long bar along which a handle travels
|
private View bar;
|
||||||
*/
|
|
||||||
protected final View mBar;
|
|
||||||
/**
|
|
||||||
* The handle that signifies the user's progress in the list
|
|
||||||
*/
|
|
||||||
protected final View mHandle;
|
|
||||||
protected RecyclerView.OnScrollListener mOnScrollListener;
|
|
||||||
protected OnTouchListener mOnTouchListener;
|
|
||||||
private RecyclerView mRecyclerView;
|
|
||||||
private AnimatorSet mAnimator;
|
|
||||||
private boolean animatingIn;
|
|
||||||
private final Runnable mHide;
|
|
||||||
private final int mMinScrollHandleHeight;
|
|
||||||
private final int mHiddenTranslationX;
|
|
||||||
|
|
||||||
public FastScroller(Context context) {
|
private RecyclerView recyclerView;
|
||||||
this(context, null, 0);
|
|
||||||
}
|
private final HandleHider handleHider = new HandleHider();
|
||||||
|
private final ScrollListener scrollListener = new ScrollListener();
|
||||||
|
|
||||||
|
private boolean isHidden;
|
||||||
|
private int hideTranslationX;
|
||||||
|
|
||||||
|
private ViewPropertyAnimator currentAnimator = null;
|
||||||
|
|
||||||
public FastScroller(Context context, AttributeSet attrs) {
|
public FastScroller(Context context, AttributeSet attrs) {
|
||||||
this(context, attrs, 0);
|
super(context, attrs);
|
||||||
|
initialise(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
public FastScroller(Context context, AttributeSet attrs, int defStyleAttr) {
|
public FastScroller(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||||
super(context, attrs, defStyleAttr);
|
super(context, attrs, defStyleAttr);
|
||||||
|
initialise(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initialise(Context context) {
|
||||||
|
hideTranslationX = getContext().getResources().getDimensionPixelSize(R.dimen.scrollbar_width) * (Util.isRTL(context) ? -1 : 1);
|
||||||
|
setClipChildren(false);
|
||||||
inflate(context, R.layout.vertical_recycler_fast_scroller_layout, this);
|
inflate(context, R.layout.vertical_recycler_fast_scroller_layout, this);
|
||||||
|
handle = findViewById(R.id.scroll_handle);
|
||||||
mBar = findViewById(R.id.scroll_bar);
|
bar = findViewById(R.id.scroll_bar);
|
||||||
mHandle = findViewById(R.id.scroll_handle);
|
handle.setEnabled(true);
|
||||||
mMinScrollHandleHeight = getResources().getDimensionPixelSize(R.dimen.min_scrollhandle_height);
|
setPressedHandleColor(ThemeSingleton.get().positiveColor);
|
||||||
|
setUpBarBackground();
|
||||||
mHiddenTranslationX = (Util.isRTL(getContext()) ? -1 : 1) * getResources().getDimensionPixelSize(R.dimen.scrollbar_width);
|
postDelayed(handleHider, HANDLE_HIDE_DELAY);
|
||||||
mHide = new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
if (!mHandle.isPressed()) {
|
|
||||||
if (mAnimator != null && mAnimator.isStarted()) {
|
|
||||||
mAnimator.cancel();
|
|
||||||
}
|
}
|
||||||
mAnimator = new AnimatorSet();
|
|
||||||
ObjectAnimator animator2 = ObjectAnimator.ofFloat(FastScroller.this, View.TRANSLATION_X,
|
|
||||||
mHiddenTranslationX);
|
|
||||||
animator2.setInterpolator(new FastOutLinearInInterpolator());
|
|
||||||
animator2.setDuration(150);
|
|
||||||
mHandle.setEnabled(false);
|
|
||||||
mAnimator.play(animator2);
|
|
||||||
mAnimator.start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
mHandle.setOnTouchListener(new OnTouchListener() {
|
|
||||||
private float mInitialBarHeight;
|
|
||||||
private float mLastPressedYAdjustedToInitial;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onTouch(View v, MotionEvent event) {
|
public boolean onTouchEvent(@NonNull MotionEvent event) {
|
||||||
mOnTouchListener.onTouch(v, event);
|
if (event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_MOVE) {
|
||||||
if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
|
setHandlePosition(event.getY());
|
||||||
mHandle.setPressed(true);
|
handle.setPressed(true);
|
||||||
|
setRecyclerViewPosition(event.getY());
|
||||||
mInitialBarHeight = getBarHeight();
|
showIfHidden();
|
||||||
mLastPressedYAdjustedToInitial = event.getY() + mHandle.getY() + mBar.getY();
|
return true;
|
||||||
} else if (event.getActionMasked() == MotionEvent.ACTION_MOVE) {
|
} else if (event.getAction() == MotionEvent.ACTION_UP) {
|
||||||
float newHandlePressedY = event.getY() + mHandle.getY() + mBar.getY();
|
handle.setPressed(false);
|
||||||
int barHeight = getBarHeight();
|
scheduleHide();
|
||||||
float newHandlePressedYAdjustedToInitial =
|
|
||||||
newHandlePressedY + (mInitialBarHeight - barHeight);
|
|
||||||
|
|
||||||
float deltaPressedYFromLastAdjustedToInitial =
|
|
||||||
newHandlePressedYAdjustedToInitial - mLastPressedYAdjustedToInitial;
|
|
||||||
|
|
||||||
int dY = (int) ((deltaPressedYFromLastAdjustedToInitial / mInitialBarHeight) *
|
|
||||||
(mRecyclerView.computeVerticalScrollRange()));
|
|
||||||
|
|
||||||
updateRvScroll(dY);
|
|
||||||
|
|
||||||
mLastPressedYAdjustedToInitial = newHandlePressedYAdjustedToInitial;
|
|
||||||
} else if (event.getActionMasked() == MotionEvent.ACTION_UP) {
|
|
||||||
mLastPressedYAdjustedToInitial = -1;
|
|
||||||
|
|
||||||
mHandle.setPressed(false);
|
|
||||||
postAutoHide();
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
return super.onTouchEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRecyclerView(RecyclerView recyclerView) {
|
||||||
|
this.recyclerView = recyclerView;
|
||||||
|
recyclerView.addOnScrollListener(scrollListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setRecyclerViewPosition(float y) {
|
||||||
|
if (recyclerView != null) {
|
||||||
|
int itemCount = recyclerView.getAdapter().getItemCount();
|
||||||
|
float proportion = y / (float) getHeightMinusPadding();
|
||||||
|
int targetPos = getValueInRange(0, itemCount - 1, (int) (proportion * (float) itemCount));
|
||||||
|
recyclerView.scrollToPosition(targetPos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getValueInRange(int min, int max, int value) {
|
||||||
|
int minimum = Math.max(min, value);
|
||||||
|
return Math.min(minimum, max);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setHandlePosition(float y) {
|
||||||
|
float position = y / getHeightMinusPadding();
|
||||||
|
int handleHeight = handle.getHeight();
|
||||||
|
handle.setY(getValueInRange(0, getHeightMinusPadding() - handleHeight, (int) ((getHeightMinusPadding() - handleHeight) * position)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showImpl() {
|
||||||
|
isHidden = false;
|
||||||
|
if (currentAnimator != null) {
|
||||||
|
currentAnimator.cancel();
|
||||||
|
}
|
||||||
|
currentAnimator = animate().translationX(0).setDuration(HANDLE_ANIMATION_DURATION);
|
||||||
|
currentAnimator.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void hideImpl() {
|
||||||
|
isHidden = true;
|
||||||
|
if (currentAnimator != null) {
|
||||||
|
currentAnimator.cancel();
|
||||||
|
}
|
||||||
|
currentAnimator = animate().translationX(hideTranslationX).setDuration(HANDLE_ANIMATION_DURATION);
|
||||||
|
currentAnimator.setListener(new AnimatorListenerAdapter() {
|
||||||
|
@Override
|
||||||
|
public void onAnimationEnd(Animator animation) {
|
||||||
|
super.onAnimationEnd(animation);
|
||||||
|
currentAnimator = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAnimationCancel(Animator animation) {
|
||||||
|
super.onAnimationCancel(animation);
|
||||||
|
currentAnimator = null;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
currentAnimator.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private class HandleHider implements Runnable {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
hideImpl();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showIfHidden() {
|
||||||
|
if (isHidden) {
|
||||||
|
getHandler().removeCallbacks(handleHider);
|
||||||
|
showImpl();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void scheduleHide() {
|
||||||
|
getHandler().removeCallbacks(handleHider);
|
||||||
|
getHandler().postDelayed(handleHider, HANDLE_HIDE_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getHeightMinusPadding() {
|
||||||
|
return getHeight() - getPaddingBottom() - getPaddingTop();
|
||||||
|
}
|
||||||
|
|
||||||
setTranslationX(mHiddenTranslationX);
|
private float computeHandlePosition() {
|
||||||
|
View firstVisibleView = recyclerView.getChildAt(0);
|
||||||
|
int firstVisiblePosition = recyclerView.getChildAdapterPosition(firstVisibleView);
|
||||||
|
int visibleRange = recyclerView.getChildCount();
|
||||||
|
int lastVisiblePosition = firstVisiblePosition + visibleRange;
|
||||||
|
int itemCount = recyclerView.getAdapter().getItemCount();
|
||||||
|
int position;
|
||||||
|
if (firstVisiblePosition == 0) {
|
||||||
|
position = 0;
|
||||||
|
} else if (lastVisiblePosition == itemCount - 1) {
|
||||||
|
position = itemCount - 1;
|
||||||
|
} else {
|
||||||
|
position = firstVisiblePosition;
|
||||||
|
}
|
||||||
|
float proportion = (float) position / (float) itemCount;
|
||||||
|
return getHeightMinusPadding() * proportion;
|
||||||
|
}
|
||||||
|
|
||||||
//Default selected handle color
|
public void updateHandlePosition() {
|
||||||
setPressedHandleColor(Color.BLACK);
|
setHandlePosition(computeHandlePosition());
|
||||||
setUpBarBackground();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides the ability to programmatically set the color of the fast scroller's handle
|
|
||||||
*/
|
|
||||||
public void setPressedHandleColor(int accent) {
|
public void setPressedHandleColor(int accent) {
|
||||||
StateListDrawable drawable = new StateListDrawable();
|
StateListDrawable drawable = new StateListDrawable();
|
||||||
|
|
||||||
|
|
@ -141,11 +189,11 @@ public class FastScroller extends FrameLayout {
|
||||||
new InsetDrawable(new ColorDrawable(colorControlNormal), getResources().getDimensionPixelSize(R.dimen.scrollbar_inset), 0, 0, 0));
|
new InsetDrawable(new ColorDrawable(colorControlNormal), getResources().getDimensionPixelSize(R.dimen.scrollbar_inset), 0, 0, 0));
|
||||||
} else {
|
} else {
|
||||||
drawable.addState(View.PRESSED_ENABLED_STATE_SET,
|
drawable.addState(View.PRESSED_ENABLED_STATE_SET,
|
||||||
new InsetDrawable(new ColorDrawable(accent), 0, getResources().getDimensionPixelSize(R.dimen.scrollbar_inset), 0, 0));
|
new InsetDrawable(new ColorDrawable(accent), 0, 0, getResources().getDimensionPixelSize(R.dimen.scrollbar_inset), 0));
|
||||||
drawable.addState(View.EMPTY_STATE_SET,
|
drawable.addState(View.EMPTY_STATE_SET,
|
||||||
new InsetDrawable(new ColorDrawable(colorControlNormal), 0, getResources().getDimensionPixelSize(R.dimen.scrollbar_inset), 0, 0));
|
new InsetDrawable(new ColorDrawable(colorControlNormal), 0, 0, getResources().getDimensionPixelSize(R.dimen.scrollbar_inset), 0));
|
||||||
}
|
}
|
||||||
mHandle.setBackground(drawable);
|
handle.setBackground(drawable);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setUpBarBackground() {
|
private void setUpBarBackground() {
|
||||||
|
|
@ -156,97 +204,17 @@ public class FastScroller extends FrameLayout {
|
||||||
if (!Util.isRTL(getContext())) {
|
if (!Util.isRTL(getContext())) {
|
||||||
drawable = new InsetDrawable(new ColorDrawable(colorControlNormal), getResources().getDimensionPixelSize(R.dimen.scrollbar_inset), 0, 0, 0);
|
drawable = new InsetDrawable(new ColorDrawable(colorControlNormal), getResources().getDimensionPixelSize(R.dimen.scrollbar_inset), 0, 0, 0);
|
||||||
} else {
|
} else {
|
||||||
drawable = new InsetDrawable(new ColorDrawable(colorControlNormal), 0, getResources().getDimensionPixelSize(R.dimen.scrollbar_inset), 0, 0);
|
drawable = new InsetDrawable(new ColorDrawable(colorControlNormal), 0, 0, getResources().getDimensionPixelSize(R.dimen.scrollbar_inset), 0);
|
||||||
}
|
}
|
||||||
mBar.setBackground(drawable);
|
bar.setBackground(drawable);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRecyclerView(RecyclerView recyclerView) {
|
private class ScrollListener extends OnScrollListener {
|
||||||
mRecyclerView = recyclerView;
|
|
||||||
initRecyclerViewOnScrollListener();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void initRecyclerViewOnScrollListener() {
|
|
||||||
mOnScrollListener = new RecyclerView.OnScrollListener() {
|
|
||||||
@Override
|
@Override
|
||||||
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
|
public void onScrolled(RecyclerView rv, int dx, int dy) {
|
||||||
super.onScrolled(recyclerView, dx, dy);
|
updateHandlePosition();
|
||||||
requestLayout();
|
showIfHidden();
|
||||||
|
scheduleHide();
|
||||||
mHandle.setEnabled(true);
|
|
||||||
if (!animatingIn && getTranslationX() != 0) {
|
|
||||||
if (mAnimator != null && mAnimator.isStarted()) {
|
|
||||||
mAnimator.cancel();
|
|
||||||
}
|
|
||||||
mAnimator = new AnimatorSet();
|
|
||||||
ObjectAnimator animator = ObjectAnimator.ofFloat(FastScroller.this, View.TRANSLATION_X, 0);
|
|
||||||
animator.setInterpolator(new LinearOutSlowInInterpolator());
|
|
||||||
animator.setDuration(100);
|
|
||||||
animator.addListener(new AnimatorListenerAdapter() {
|
|
||||||
@Override
|
|
||||||
public void onAnimationEnd(Animator animation) {
|
|
||||||
super.onAnimationEnd(animation);
|
|
||||||
animatingIn = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
animatingIn = true;
|
|
||||||
mAnimator.play(animator);
|
|
||||||
mAnimator.start();
|
|
||||||
}
|
|
||||||
postAutoHide();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
mRecyclerView.addOnScrollListener(mOnScrollListener);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOnHandleTouchListener(OnTouchListener listener) {
|
|
||||||
mOnTouchListener = listener;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void postAutoHide() {
|
|
||||||
if (mRecyclerView != null) {
|
|
||||||
mRecyclerView.removeCallbacks(mHide);
|
|
||||||
mRecyclerView.postDelayed(mHide, 1500);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
|
||||||
super.onLayout(changed, left, top, right, bottom);
|
|
||||||
|
|
||||||
int scrollOffset = mRecyclerView.computeVerticalScrollOffset();
|
|
||||||
int verticalScrollRange = mRecyclerView.computeVerticalScrollRange()
|
|
||||||
+ mRecyclerView.getPaddingBottom();
|
|
||||||
|
|
||||||
int barHeight = getBarHeight();
|
|
||||||
float ratio = (float) scrollOffset / (verticalScrollRange - barHeight);
|
|
||||||
|
|
||||||
int calculatedHandleHeight = (int) ((float) barHeight / verticalScrollRange * barHeight);
|
|
||||||
if (calculatedHandleHeight < mMinScrollHandleHeight) {
|
|
||||||
calculatedHandleHeight = mMinScrollHandleHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (calculatedHandleHeight >= barHeight) {
|
|
||||||
setTranslationX(mHiddenTranslationX);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
float y = ratio * (barHeight - calculatedHandleHeight);
|
|
||||||
|
|
||||||
mHandle.layout(mHandle.getLeft(), (int) y, mHandle.getRight(), (int) y + calculatedHandleHeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateRvScroll(int dY) {
|
|
||||||
if (mRecyclerView != null && mHandle != null) {
|
|
||||||
try {
|
|
||||||
mRecyclerView.scrollBy(0, dY);
|
|
||||||
} catch (Throwable t) {
|
|
||||||
t.printStackTrace();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getBarHeight() {
|
|
||||||
return mBar.getHeight();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,20 +1,20 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="48dp"
|
android:layout_width="@dimen/scrollbar_width_plus_inset"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
tools:layout_gravity="end">
|
tools:layout_gravity="end">
|
||||||
|
|
||||||
<View
|
<View
|
||||||
android:id="@+id/scroll_bar"
|
android:id="@+id/scroll_bar"
|
||||||
android:layout_width="48dp"
|
android:layout_width="@dimen/scrollbar_width_plus_inset"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_gravity="end"
|
android:layout_gravity="end"
|
||||||
android:alpha="0.22352941176" />
|
android:alpha="0.3" />
|
||||||
|
|
||||||
<View
|
<View
|
||||||
android:id="@+id/scroll_handle"
|
android:id="@+id/scroll_handle"
|
||||||
android:layout_width="48dp"
|
android:layout_width="@dimen/scrollbar_width_plus_inset"
|
||||||
android:layout_height="48dp"
|
android:layout_height="48dp"
|
||||||
android:layout_gravity="end" />
|
android:layout_gravity="end" />
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -51,9 +51,10 @@ http://developer.android.com/guide/topics/appwidgets/index.html#CreatingLayout
|
||||||
<dimen name="notification_albumart_size">128dp</dimen>
|
<dimen name="notification_albumart_size">128dp</dimen>
|
||||||
<dimen name="bottom_offset_fab_activity">86dp</dimen>
|
<dimen name="bottom_offset_fab_activity">86dp</dimen>
|
||||||
|
|
||||||
<dimen name="min_scrollhandle_height">48dp</dimen>
|
|
||||||
<dimen name="scrollbar_width">8dp</dimen>
|
<dimen name="scrollbar_width">8dp</dimen>
|
||||||
<dimen name="scrollbar_inset">40dp</dimen>
|
<dimen name="scrollbar_inset">8dp</dimen>
|
||||||
|
<!-- MUST BE THE RESULT OF WIDTH PLUS INSET-->
|
||||||
|
<dimen name="scrollbar_width_plus_inset">16dp</dimen>
|
||||||
|
|
||||||
<!-- ONLY 0dp WHILE THERE IS THE BUG IN DESIGN SUPPORT LIBRARY 22.2.0-->
|
<!-- ONLY 0dp WHILE THERE IS THE BUG IN DESIGN SUPPORT LIBRARY 22.2.0-->
|
||||||
<dimen name="fab_margin">0dp</dimen>
|
<dimen name="fab_margin">0dp</dimen>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue