From 75222c4321d5d2c51b49f82fcc9212994c6ace99 Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Mon, 26 Oct 2015 17:14:23 -0700 Subject: More work on smooth scrolling + getting it to work on grid managers --- .../github/daneren2005/dsub/view/FastScroller.java | 75 +++++++++++++++++++++- 1 file changed, 72 insertions(+), 3 deletions(-) (limited to 'app/src') diff --git a/app/src/main/java/github/daneren2005/dsub/view/FastScroller.java b/app/src/main/java/github/daneren2005/dsub/view/FastScroller.java index bdfde1cf..ba83e46c 100644 --- a/app/src/main/java/github/daneren2005/dsub/view/FastScroller.java +++ b/app/src/main/java/github/daneren2005/dsub/view/FastScroller.java @@ -23,6 +23,7 @@ import android.content.Context; import android.support.annotation.NonNull; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.RecyclerView.AdapterDataObserver; import android.util.AttributeSet; import android.util.Log; import android.view.LayoutInflater; @@ -45,6 +46,9 @@ public class FastScroller extends LinearLayout { private RecyclerView recyclerView; private final ScrollListener scrollListener = new ScrollListener(); private int height; + private int visibleRange = -1; + private RecyclerView.Adapter adapter; + private AdapterDataObserver adapterObserver; private boolean visibleBubble = true; private boolean hasScrolled = false; @@ -80,6 +84,7 @@ public class FastScroller extends LinearLayout { protected void onSizeChanged(int w,int h,int oldw,int oldh) { super.onSizeChanged(w,h,oldw,oldh); height = h; + visibleRange = -1; } @Override @@ -121,10 +126,13 @@ public class FastScroller extends LinearLayout { public void attachRecyclerView(RecyclerView recyclerView) { this.recyclerView = recyclerView; recyclerView.addOnScrollListener(scrollListener); + registerAdapter(); + visibleRange = -1; } public void detachRecyclerView() { recyclerView.removeOnScrollListener(scrollListener); recyclerView.setVerticalScrollBarEnabled(true); + unregisterAdapter(); recyclerView = null; setVisibility(View.GONE); } @@ -147,7 +155,12 @@ public class FastScroller extends LinearLayout { ((LinearLayoutManager)recyclerView.getLayoutManager()).scrollToPositionWithOffset(targetPos,0); try { - String bubbleText = ((BubbleTextGetter) recyclerView.getAdapter()).getTextToShowInBubble(targetPos); + String bubbleText = null; + RecyclerView.Adapter adapter = recyclerView.getAdapter(); + if(adapter instanceof BubbleTextGetter) { + bubbleText = ((BubbleTextGetter) adapter).getTextToShowInBubble(targetPos); + } + if(bubbleText == null) { visibleBubble = false; bubble.setVisibility(View.INVISIBLE); @@ -203,16 +216,72 @@ public class FastScroller extends LinearLayout { currentAnimator.start(); } + private void registerAdapter() { + RecyclerView.Adapter newAdapter = recyclerView.getAdapter(); + if(newAdapter != adapter) { + unregisterAdapter(); + } + + if(newAdapter != null) { + adapterObserver = new AdapterDataObserver() { + @Override + public void onChanged() { + visibleRange = -1; + } + + @Override + public void onItemRangeChanged(int positionStart, int itemCount) { + visibleRange = -1; + } + + @Override + public void onItemRangeInserted(int positionStart, int itemCount) { + visibleRange = -1; + } + + @Override + public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) { + visibleRange = -1; + } + + @Override + public void onItemRangeRemoved(int positionStart, int itemCount) { + visibleRange = -1; + } + }; + newAdapter.registerAdapterDataObserver(adapterObserver); + adapter = newAdapter; + } + } + private void unregisterAdapter() { + if(adapter != null) { + adapter.unregisterAdapterDataObserver(adapterObserver); + adapter = null; + adapterObserver = null; + } + } + private class ScrollListener extends OnScrollListener { @Override public void onScrolled(RecyclerView rv,int dx,int dy) { + registerAdapter(); + View firstVisibleView = recyclerView.getChildAt(0); int firstVisiblePosition = recyclerView.getChildPosition(firstVisibleView); - int visibleRange = recyclerView.getChildCount(); + if(visibleRange == -1) { + visibleRange = recyclerView.getChildCount(); + } int itemCount = recyclerView.getAdapter().getItemCount(); + int columns = Math.round(recyclerView.getWidth() / firstVisibleView.getWidth()); // Add the percentage of the item the user has scrolled past already - float position = firstVisiblePosition + (-firstVisibleView.getY() / firstVisibleView.getHeight()); + float pastFirst = -firstVisibleView.getY() / firstVisibleView.getHeight() * columns; + float position = firstVisiblePosition + pastFirst; + + // Scale this so as we move down the visible range gets added to position from 0 -> visible range + float scaledVisibleRange = position / (float) (itemCount - visibleRange) * visibleRange; + position += scaledVisibleRange; + float proportion = position / itemCount; setBubbleAndHandlePosition(height * proportion); -- cgit v1.2.3