diff --git a/recyclerviewfastscroller/src/main/java/xyz/danoz/recyclerviewfastscroller/AbsRecyclerViewFastScroller.java b/recyclerviewfastscroller/src/main/java/xyz/danoz/recyclerviewfastscroller/AbsRecyclerViewFastScroller.java index 5b88dfc..e2fa63a 100644 --- a/recyclerviewfastscroller/src/main/java/xyz/danoz/recyclerviewfastscroller/AbsRecyclerViewFastScroller.java +++ b/recyclerviewfastscroller/src/main/java/xyz/danoz/recyclerviewfastscroller/AbsRecyclerViewFastScroller.java @@ -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; @@ -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 @@ -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()); @@ -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) { @@ -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. @@ -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) { @@ -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; + } } \ No newline at end of file