Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import android.graphics.drawable.Drawable;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.widget.RecyclerView;
Expand Down Expand Up @@ -36,6 +37,13 @@ public abstract class AbsRecyclerViewFastScroller extends FrameLayout implements
/** The handle that signifies the user's progress in the list */
protected final View mHandle;

private boolean mFastScrollAlwaysVisible;
private boolean mIsVisible;
private long mFastScrollTimeout;
private long mEventTime;
private Handler mVisibilityHandler;
private Runnable mVisibilityRunner;

/* TODO:
* Consider making RecyclerView final and should be passed in using a custom attribute
* This could allow for some type checking on the section indicator wrt the adapter of the RecyclerView
Expand All @@ -60,6 +68,9 @@ public AbsRecyclerViewFastScroller(Context context, AttributeSet attrs, int defS

TypedArray attributes = getContext().getTheme().obtainStyledAttributes(attrs, STYLEABLE, 0, 0);

mFastScrollAlwaysVisible = true;
mFastScrollTimeout = 10000;

try {
int layoutResource = attributes.getResourceId(R.styleable.AbsRecyclerViewFastScroller_rfs_fast_scroller_layout,
getLayoutResourceId());
Expand Down Expand Up @@ -136,6 +147,7 @@ private void setViewBackground(View view, Drawable background) {
@Override
public void setRecyclerView(RecyclerView recyclerView) {
mRecyclerView = recyclerView;
addOnTouchListener();
}

public void setSectionIndicator(SectionIndicator sectionIndicator) {
Expand Down Expand Up @@ -171,6 +183,51 @@ private int getPositionFromScrollProgress(float scrollProgress) {
return (int) (mRecyclerView.getAdapter().getItemCount() * scrollProgress);
}

/**
* Detect if we touch the recyclerview. Make visible if we did and set to be invisible.
*/
private void addOnTouchListener() {
mHandle.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
if (!mFastScrollAlwaysVisible) {
mEventTime = System.currentTimeMillis();
setVisible();
}
break;
case MotionEvent.ACTION_UP:
if (!mFastScrollAlwaysVisible) {
mEventTime = System.currentTimeMillis();
}
break;
}
return false;
}
});

mRecyclerView.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
if (!mFastScrollAlwaysVisible) {
mEventTime = System.currentTimeMillis();
setVisible();
}
break;
case MotionEvent.ACTION_UP:
if (!mFastScrollAlwaysVisible) {
mEventTime = System.currentTimeMillis();
}
break;
}
return false;
}
});
}

/**
* Classes that extend AbsFastScroller must implement their own {@link OnScrollListener} to respond to scroll
* events when the {@link #mRecyclerView} is scrolled NOT using the fast scroller.
Expand All @@ -181,7 +238,14 @@ public OnScrollListener getOnScrollListener() {
if (mOnScrollListener == null) {
mOnScrollListener = new OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
public void onScrolled(final RecyclerView recyclerView, int dx, int dy) {
if (!mFastScrollAlwaysVisible) {
mEventTime = System.currentTimeMillis();
if (dx != 0 && !mFastScrollAlwaysVisible) {
setVisible();
}
}

float scrollProgress = 0;
ScrollProgressCalculator scrollProgressCalculator = getScrollProgressCalculator();
if (scrollProgressCalculator != null) {
Expand Down Expand Up @@ -245,4 +309,76 @@ public float getScrollProgress(MotionEvent event) {
*/
public abstract void moveHandleToPosition(float scrollProgress);

/**
* Set whether to always show or use the AbsListView behaviour.
* @param scrollAlwaysVisible
*/
public void setScrollAlwaysVisible(boolean scrollAlwaysVisible) {
mFastScrollAlwaysVisible = scrollAlwaysVisible;
if (!mFastScrollAlwaysVisible) {
setInvisible();
if (mVisibilityHandler == null) {
mVisibilityHandler = new Handler();
}
mVisibilityRunner = new Runnable() {
public void run() {
long end = mEventTime + mFastScrollTimeout;
long time = System.currentTimeMillis();
if (end < time && mIsVisible) {
setInvisible();
}
try {
mVisibilityHandler.postDelayed(this, 333);
} catch (Exception e) {
e.printStackTrace();
}
}
};
mVisibilityHandler.post(mVisibilityRunner);
}
}

/**
* Set timeout value.
* @param desiredTimeout
*/
public void setTimeout(long desiredTimeout) {
mFastScrollTimeout = desiredTimeout;
if (mFastScrollTimeout < 3000) {
mFastScrollTimeout = 3000;
}
}

/**
*
*/
public long getTimeout() {
return mFastScrollTimeout;
}

/**
* Get scroll visibility status.
* @return scroll visibility status
*/
public boolean getScrollAlwaysVisible() {
return mFastScrollAlwaysVisible;
}

/**
* Set bar and handle to be invisible
*/
private void setInvisible() {
mBar.setVisibility(View.INVISIBLE);
mHandle.setVisibility(View.INVISIBLE);
mIsVisible = false;
}

/**
* Set bar and handle to be visible
*/
private void setVisible() {
mBar.setVisibility(View.VISIBLE);
mHandle.setVisibility(View.VISIBLE);
mIsVisible = true;
}
}