From cbeea129b635798480d268388cce074cdd3fc41b Mon Sep 17 00:00:00 2001 From: draekko Date: Sat, 29 Aug 2015 14:56:19 -0400 Subject: [PATCH 1/4] == 2015-08-29 == Adds the option to setVisibility with a timeout value similar to behaviour of ListView fastscroll. Default timeout value set to 10 seconds. Adds : * public void setTimeout(long desiredTimeout) * public long getTimeout() * public void setScrollAlwaysVisible(boolean scrollAlwaysVisible) * public boolean getScrollAlwaysVisible() --- .../AbsRecyclerViewFastScroller.java | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/recyclerviewfastscroller/src/main/java/xyz/danoz/recyclerviewfastscroller/AbsRecyclerViewFastScroller.java b/recyclerviewfastscroller/src/main/java/xyz/danoz/recyclerviewfastscroller/AbsRecyclerViewFastScroller.java index 5b88dfc..6c2cc69 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,11 @@ 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 Handler mVisibilityHandler; + /* 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 +66,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()); @@ -81,6 +90,10 @@ public AbsRecyclerViewFastScroller(Context context, AttributeSet attrs, int defS } setOnTouchListener(new FastScrollerTouchListener(this)); + + if (!mFastScrollAlwaysVisible) { + setInvisible(); + } } private void applyCustomAttributesToView(View view, Drawable drawable, int color) { @@ -136,6 +149,7 @@ private void setViewBackground(View view, Drawable background) { @Override public void setRecyclerView(RecyclerView recyclerView) { mRecyclerView = recyclerView; + addOnTouchListener(); } public void setSectionIndicator(SectionIndicator sectionIndicator) { @@ -171,6 +185,36 @@ private int getPositionFromScrollProgress(float scrollProgress) { return (int) (mRecyclerView.getAdapter().getItemCount() * scrollProgress); } + private void addOnTouchListener() { + mRecyclerView.setOnTouchListener(new OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + switch (event.getActionMasked()) { + case MotionEvent.ACTION_DOWN: + if (!mIsVisible && mVisibilityHandler == null) { + try { + mVisibilityHandler = new Handler(); + mVisibilityHandler.postDelayed(new Runnable() { + @Override + public void run() { + setInvisible(); + mVisibilityHandler = null; + } + }, mFastScrollTimeout); + } catch (Exception e) { + } + } else if (!mIsVisible && mVisibilityHandler != null) { + setVisible(); + } + break; + case MotionEvent.ACTION_UP: + 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. @@ -182,6 +226,24 @@ public OnScrollListener getOnScrollListener() { mOnScrollListener = new OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { + if (!mFastScrollAlwaysVisible && dy > 0) { + if (!mIsVisible && mVisibilityHandler == null) { + setVisible(); + try { + mVisibilityHandler = new Handler(); + mVisibilityHandler.postDelayed(new Runnable() { + @Override + public void run() { + setInvisible(); + mVisibilityHandler = null; + } + }, mFastScrollTimeout); + } catch (Exception e) { + } + } else if (!mIsVisible && mVisibilityHandler != null) { + setVisible(); + } + } float scrollProgress = 0; ScrollProgressCalculator scrollProgressCalculator = getScrollProgressCalculator(); if (scrollProgressCalculator != null) { @@ -245,4 +307,40 @@ 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(); + } + } + + /** + * 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 From 6e13f01367566a0d0dde0526b4d6b2776a860e8b Mon Sep 17 00:00:00 2001 From: draekko Date: Sat, 29 Aug 2015 15:00:58 -0400 Subject: [PATCH 2/4] == 2015-08-29 == Add missing functions that should have been added in previous commit to set/get timeout value. --- .../AbsRecyclerViewFastScroller.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/recyclerviewfastscroller/src/main/java/xyz/danoz/recyclerviewfastscroller/AbsRecyclerViewFastScroller.java b/recyclerviewfastscroller/src/main/java/xyz/danoz/recyclerviewfastscroller/AbsRecyclerViewFastScroller.java index 6c2cc69..f2d4869 100644 --- a/recyclerviewfastscroller/src/main/java/xyz/danoz/recyclerviewfastscroller/AbsRecyclerViewFastScroller.java +++ b/recyclerviewfastscroller/src/main/java/xyz/danoz/recyclerviewfastscroller/AbsRecyclerViewFastScroller.java @@ -318,6 +318,21 @@ public void setScrollAlwaysVisible(boolean scrollAlwaysVisible) { } } + /** + * Set timeout value. + * @param desiredTimeout + */ + public void setTimeout(long desiredTimeout) { + mFastScrollTimeout = desiredTimeout; + } + + /** + * + */ + public long getTimeout() { + return mFastScrollTimeout; + } + /** * Get scroll visibility status. * @return scroll visibility status From c78f57488bd20634753f657a7fc490c320bb43bf Mon Sep 17 00:00:00 2001 From: draekko Date: Sat, 29 Aug 2015 15:10:03 -0400 Subject: [PATCH 3/4] Fix to also catch negative deltas for vertical change Fix to also catch negative deltas for vertical change. --- .../recyclerviewfastscroller/AbsRecyclerViewFastScroller.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/recyclerviewfastscroller/src/main/java/xyz/danoz/recyclerviewfastscroller/AbsRecyclerViewFastScroller.java b/recyclerviewfastscroller/src/main/java/xyz/danoz/recyclerviewfastscroller/AbsRecyclerViewFastScroller.java index f2d4869..ed91dbc 100644 --- a/recyclerviewfastscroller/src/main/java/xyz/danoz/recyclerviewfastscroller/AbsRecyclerViewFastScroller.java +++ b/recyclerviewfastscroller/src/main/java/xyz/danoz/recyclerviewfastscroller/AbsRecyclerViewFastScroller.java @@ -226,7 +226,7 @@ public OnScrollListener getOnScrollListener() { mOnScrollListener = new OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { - if (!mFastScrollAlwaysVisible && dy > 0) { + if (!mFastScrollAlwaysVisible && dy != 0) { if (!mIsVisible && mVisibilityHandler == null) { setVisible(); try { @@ -358,4 +358,4 @@ private void setVisible() { mHandle.setVisibility(View.VISIBLE); mIsVisible = true; } -} \ No newline at end of file +} From 01317cabfb8f140229415ca8b475f68716ea70e2 Mon Sep 17 00:00:00 2001 From: draekko Date: Sat, 29 Aug 2015 18:36:34 -0400 Subject: [PATCH 4/4] == 2015-08-29 == Fixed event handler to timeout properly on set timeout. Added minimum timeout check of 3000ms. --- .../AbsRecyclerViewFastScroller.java | 91 ++++++++++++------- 1 file changed, 57 insertions(+), 34 deletions(-) diff --git a/recyclerviewfastscroller/src/main/java/xyz/danoz/recyclerviewfastscroller/AbsRecyclerViewFastScroller.java b/recyclerviewfastscroller/src/main/java/xyz/danoz/recyclerviewfastscroller/AbsRecyclerViewFastScroller.java index ed91dbc..e2fa63a 100644 --- a/recyclerviewfastscroller/src/main/java/xyz/danoz/recyclerviewfastscroller/AbsRecyclerViewFastScroller.java +++ b/recyclerviewfastscroller/src/main/java/xyz/danoz/recyclerviewfastscroller/AbsRecyclerViewFastScroller.java @@ -40,7 +40,9 @@ public abstract class AbsRecyclerViewFastScroller extends FrameLayout implements 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 @@ -90,10 +92,6 @@ public AbsRecyclerViewFastScroller(Context context, AttributeSet attrs, int defS } setOnTouchListener(new FastScrollerTouchListener(this)); - - if (!mFastScrollAlwaysVisible) { - setInvisible(); - } } private void applyCustomAttributesToView(View view, Drawable drawable, int color) { @@ -185,29 +183,44 @@ 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 (!mIsVisible && mVisibilityHandler == null) { - try { - mVisibilityHandler = new Handler(); - mVisibilityHandler.postDelayed(new Runnable() { - @Override - public void run() { - setInvisible(); - mVisibilityHandler = null; - } - }, mFastScrollTimeout); - } catch (Exception e) { - } - } else if (!mIsVisible && mVisibilityHandler != null) { + if (!mFastScrollAlwaysVisible) { + mEventTime = System.currentTimeMillis(); setVisible(); } break; case MotionEvent.ACTION_UP: + if (!mFastScrollAlwaysVisible) { + mEventTime = System.currentTimeMillis(); + } break; } return false; @@ -225,25 +238,14 @@ public OnScrollListener getOnScrollListener() { if (mOnScrollListener == null) { mOnScrollListener = new OnScrollListener() { @Override - public void onScrolled(RecyclerView recyclerView, int dx, int dy) { - if (!mFastScrollAlwaysVisible && dy != 0) { - if (!mIsVisible && mVisibilityHandler == null) { - setVisible(); - try { - mVisibilityHandler = new Handler(); - mVisibilityHandler.postDelayed(new Runnable() { - @Override - public void run() { - setInvisible(); - mVisibilityHandler = null; - } - }, mFastScrollTimeout); - } catch (Exception e) { - } - } else if (!mIsVisible && mVisibilityHandler != null) { + 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) { @@ -315,6 +317,24 @@ 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); } } @@ -324,6 +344,9 @@ public void setScrollAlwaysVisible(boolean scrollAlwaysVisible) { */ public void setTimeout(long desiredTimeout) { mFastScrollTimeout = desiredTimeout; + if (mFastScrollTimeout < 3000) { + mFastScrollTimeout = 3000; + } } /** @@ -358,4 +381,4 @@ private void setVisible() { mHandle.setVisibility(View.VISIBLE); mIsVisible = true; } -} +} \ No newline at end of file