Ich bin vor ein paar Tagen über diese Frage gestolpert, als ich auf diese Situation gestoßen bin. Hier ist meine Beispielimplementierung von FastScroll für RecyclerView :
Versuchen Sie, die Beispielanwendung auszuführen, und lesen Sie den Code durch, um eine recht einfache Verwendung eines einfachen RecyclerViewFastScroller-Widgets zu sehen. Es gibt Informationen zu Github, aber ich werde hier die grundlegende Verwendung für einen vertikalen schnellen Scroller einschließen.
Ein vollständiges Beispiel finden Sie in der Beispielanwendung im Repo .
Grundlegende Verwendung
Fügen Sie in die Aktivitäts- oder Fragment-XML-Datei, in der sich Ihre RecyclerView befindet, ein VerticalRecyclerViewFastScroller-Objekt ein. Das folgende Beispiel wäre in einem relativen Layout:
...
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<xyz.danoz.recyclerviewfastscroller.vertical.VerticalRecyclerViewFastScroller
android:id="@+id/fast_scroller"
android:layout_width="@dimen/however_wide_you_want_this"
android:layout_height="match_parent"
android:layout_alignParentRight="true"
/>
...
Schließen Sie in Ihrem Fragment oder Ihrer Aktivität, in der Sie das Layout programmgesteuert einrichten, den schnellen Scroller an den Recycler an:
...
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.recycler_view_frag, container, false);
...
RecyclerView recyclerView = (RecyclerView) rootView.findViewById(R.id.recyclerView);
VerticalRecyclerViewFastScroller fastScroller = (VerticalRecyclerViewFastScroller) rootView.findViewById(R.id.fast_scroller);
fastScroller.setRecyclerView(recyclerView);
recyclerView.setOnScrollListener(fastScroller.getOnScrollListener());
...
return rootView;
}
...
Hoffe das hilft!
BEARBEITEN : Es gibt jetzt Unterstützung für Abschnittsindikatoren im Android-Lollipop-Kontakt-Stil! Weitere Informationen finden Sie in der Implementierung der Beispielanwendung.
Neue Antwort: Im Laufe der Zeit habe ich festgestellt, dass meine ursprüngliche Antwort im Vergleich zu anderen Lösungen einige Nachteile hatte, insbesondere bei Fragmenten in ViewPager.
Ich schlage vor, entweder die Android-X-Lösung zu verwenden, falls Sie keine Blase benötigen, oder eine Bibliothek eines Drittanbieters ( hier ist eine nette), falls Sie dies tun.
alte Antwort:
Da alle Bibliotheken von Drittanbietern Probleme hatten, habe ich beschlossen, zu sammeln, was ich finden kann (meistens von hier ), alles zu reparieren und meinen eigenen POC des Fast-Scrollers von RecyclerView zu veröffentlichen:
https://github.com/AndroidDeveloperLB/LollipopContactsRecyclerViewFastScroller
Verwendung:
Erstellen Sie einen RecyclerView.Adapter, der BubbleTextGetter implementiert. Wenn Sie eine Position in den Daten angeben, wird der Text zurückgegeben, der im Bubble-Popup angezeigt wird.
Positionieren Sie den FastScroller innerhalb des Layouts, das die RecyclerView enthält (wahrscheinlich im richtigen Bereich).
Passen Sie den FastScroller FastScroller an
Einige Nachteile:
Code:
BubbleTextGetter
public interface BubbleTextGetter { String getTextToShowInBubble(int pos); }
recycler_view_fast_scroller__fast_scroller.xml
<?xml version="1.0" encoding="utf-8"?> <merge xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="wrap_content" android:layout_height="match_parent"> <TextView android:id="@+id/fastscroller_bubble" android:layout_gravity="right|end" android:gravity="center" android:textSize="48sp" tools:text="A" android:layout_width="wrap_content" android:textColor="#FFffffff" android:layout_height="wrap_content" android:background="@drawable/recycler_view_fast_scroller__bubble" android:visibility="visible"/> <ImageView android:id="@+id/fastscroller_handle" android:layout_width="wrap_content" android:layout_marginRight="8dp" android:layout_marginLeft="8dp" android:layout_height="wrap_content" android:src="@drawable/recycler_view_fast_scroller__handle"/> </merge>
Hauptaktivität
FastScroller
public class FastScroller extends LinearLayout { private static final int BUBBLE_ANIMATION_DURATION=100; private static final int TRACK_SNAP_RANGE=5; private TextView bubble; private View handle; private RecyclerView recyclerView; private final ScrollListener scrollListener=new ScrollListener(); private int height; private ObjectAnimator currentAnimator=null; public FastScroller(final Context context,final AttributeSet attrs,final int defStyleAttr) { super(context,attrs,defStyleAttr); initialise(context); } public FastScroller(final Context context) { super(context); initialise(context); } public FastScroller(final Context context,final AttributeSet attrs) { super(context,attrs); initialise(context); } private void initialise(Context context) { setOrientation(HORIZONTAL); setClipChildren(false); LayoutInflater inflater=LayoutInflater.from(context); inflater.inflate(R.layout.recycler_view_fast_scroller__fast_scroller,this,true); bubble=(TextView)findViewById(R.id.fastscroller_bubble); handle=findViewById(R.id.fastscroller_handle); bubble.setVisibility(INVISIBLE); } @Override protected void onSizeChanged(int w,int h,int oldw,int oldh) { super.onSizeChanged(w,h,oldw,oldh); height=h; } @Override public boolean onTouchEvent(@NonNull MotionEvent event) { final int action=event.getAction(); switch(action) { case MotionEvent.ACTION_DOWN: if(event.getX()<handle.getX()) return false; if(currentAnimator!=null) currentAnimator.cancel(); if(bubble.getVisibility()==INVISIBLE) showBubble(); handle.setSelected(true); case MotionEvent.ACTION_MOVE: setPosition(event.getY()); setRecyclerViewPosition(event.getY()); return true; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: handle.setSelected(false); hideBubble(); return true; } return super.onTouchEvent(event); } public void setRecyclerView(RecyclerView recyclerView) { this.recyclerView=recyclerView; recyclerView.setOnScrollListener(scrollListener); } private void setRecyclerViewPosition(float y) { if(recyclerView!=null) { int itemCount=recyclerView.getAdapter().getItemCount(); float proportion; if(handle.getY()==0) proportion=0f; else if(handle.getY()+handle.getHeight()>=height-TRACK_SNAP_RANGE) proportion=1f; else proportion=y/(float)height; int targetPos=getValueInRange(0,itemCount-1,(int)(proportion*(float)itemCount)); recyclerView.scrollToPosition(targetPos); String bubbleText=((BubbleTextGetter)recyclerView.getAdapter()).getTextToShowInBubble(targetPos); bubble.setText(bubbleText); } } private int getValueInRange(int min,int max,int value) { int minimum=Math.max(min,value); return Math.min(minimum,max); } private void setPosition(float y) { int bubbleHeight=bubble.getHeight(); int handleHeight=handle.getHeight(); handle.setY(getValueInRange(0,height-handleHeight,(int)(y-handleHeight/2))); bubble.setY(getValueInRange(0,height-bubbleHeight-handleHeight/2,(int)(y-bubbleHeight))); } private void showBubble() { AnimatorSet animatorSet=new AnimatorSet(); bubble.setVisibility(VISIBLE); if(currentAnimator!=null) currentAnimator.cancel(); currentAnimator=ObjectAnimator.ofFloat(bubble,"alpha",0f,1f).setDuration(BUBBLE_ANIMATION_DURATION); currentAnimator.start(); } private void hideBubble() { if(currentAnimator!=null) currentAnimator.cancel(); currentAnimator=ObjectAnimator.ofFloat(bubble,"alpha",1f,0f).setDuration(BUBBLE_ANIMATION_DURATION); currentAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); bubble.setVisibility(INVISIBLE); currentAnimator=null; } @Override public void onAnimationCancel(Animator animation) { super.onAnimationCancel(animation); bubble.setVisibility(INVISIBLE); currentAnimator=null; } }); currentAnimator.start(); } private class ScrollListener extends OnScrollListener { @Override public void onScrolled(RecyclerView rv,int dx,int dy) { View firstVisibleView=recyclerView.getChildAt(0); int firstVisiblePosition=recyclerView.getChildPosition(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; setPosition(height*proportion); } } }
quelle
Es gibt viele unbeantwortete Fragen zu
RecyclerView
und zum schnellen Scrollen / Abschnittsindexieren. Versuchen wir, unsere Meinungen und Informationen hier neu zu gruppieren und zu sammeln.Die kurze Antwort lautet: NEIN, Sie können den schnellen Bildlauf nicht aktivieren, da RecyclerView weder ein FastScroller- Objekt noch verwandte logische Statusvariablen enthält. Dies liegt daran, dass
RecyclerView
es sich nicht um eine AbsListView handelt .Auf der anderen Seite ist es nicht unmöglich, eine zu implementieren,
RecyclerView
die eine gedumpte Version vonFastScroller
und die notwendige Logik für das schnelle Scrollen enthält, aber ich habe bisher keine Implementierung davon gesehen.Bitte teilen Sie Ihre Überlegungen dazu oder wenn Sie denken, dass ich falsch liege.
quelle
RecyclerView
war nicht für die Verwendung mit einem FastScroller gedacht. Es ist gegen seine Philosophie und Gestaltungsidee der unendlichen Liste. Aber nichtsDie Android Support Library 26.0.0 unterstützt jetzt
fastScrollEnabled
Neues boolesches Flag fastScrollEnabled für RecyclerView.
Wenn aktiviert, müssen fastScrollHorizontalThumbDrawable, fastScrollHorizontalTrackDrawable, fastScrollVerticalThumbDrawable und fastScrollVerticalTrackDrawable festgelegt werden.
Beispiel - https://android.jlelse.eu/fast-scrolling-with-recyclerview-2b89d4574688
quelle
state_pressed="true"
, Artikel mitstate_selected="true"
und nur den normalen Artikel innerhalb der implementierenselector
. Sie haben also 3 Elemente in der Auswahl.Sie können AZ Fastscroll auch für RecyclerView verwenden. Es ist der iOS-Stil.
https://github.com/code-computerlove/FastScrollRecyclerView/
Wie man es benutzt:
android.support.v7.widget.RecyclerView
durchcom.codecomputerlove.fastscrollrecyclerviewdemo.FastScrollRecyclerView
getMapIndex()
. Die Funktion sollte den mapIndex zurückgeben. Lassen Sie sichcalculateIndexesForName()
inspirieren, wie Sie es erstellen können. Einmal erstellt, übergeben Sie es an den Adapter im Konstruktor.FastScrollRecyclerViewItemDecoration
und fügen Sie sie Ihrem RecyclerView hinzuFastScrollRecyclerViewItemDecoration decoration = new FastScrollRecyclerViewItemDecoration(this); mRecyclerView.addItemDecoration(decoration);
<dimen name="fast_scroll_overlay_text_size">100dp</dimen>
zu Ihrer/values/dimens.xml
Datei hinzufügen . Dies ist die dp-Größe des überlagerten Buchstabensquelle
Die FastScroller-Funktionalität wurde aus der Android-Bibliothek 26.0.0 für RecyclerView hinzugefügt
Abhängigkeit kompilieren
compile 'com.android.support:recyclerview-v7:26.1.0' compile 'com.android.support:design:26.1.0'
füge depentency zu project.gradle hinzu
maven { url "https://maven.google.com" }
Ihre recyclerview.xml-Datei
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" xmlns:tool="http://schemas.android.com/tools" android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto" android:orientation="vertical" tool:context=".MainActivity"> <android.support.v7.widget.RecyclerView android:layout_width="match_parent" android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/songlist" android:layout_marginStart="8dp" android:layout_marginEnd="8dp" app:fastScrollEnabled="true" app:fastScrollVerticalThumbDrawable="@drawable/thumb_drawable" app:fastScrollVerticalTrackDrawable="@drawable/line_drawable" app:fastScrollHorizontalThumbDrawable="@drawable/thumb_drawable" app:fastScrollHorizontalTrackDrawable="@drawable/line_drawable" /></LinearLayout>
thumb.xml
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <corners android:topLeftRadius="44dp" android:topRightRadius="44dp" android:bottomLeftRadius="44dp" android:bottomRightRadius="44dp" /> <padding android:paddingLeft="22dp" android:paddingRight="22dp" /> <solid android:color="#f73831" /> </shape>
line.xml
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <solid android:color="@color/dark_grey" /> <padding android:top="10dp" android:left="10dp" android:right="10dp" android:bottom="10dp"/> </shape>
thumb_drawable.xml
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/thumb" android:state_focused="true" android:state_pressed="true" /> <item android:drawable="@drawable/thumb" android:state_focused="false" android:state_pressed="true" /> <item android:drawable="@drawable/thumb" android:state_focused="true" /> <item android:drawable="@drawable/thumb" android:state_focused="false" android:state_pressed="false" /> </selector>
line_drawble.xml
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/line" android:state_focused="true" android:state_pressed="true" /> <item android:drawable="@drawable/line" android:state_focused="false" android:state_pressed="true" /> <item android:drawable="@drawable/line" android:state_focused="true" /> <item android:drawable="@drawable/line" android:state_focused="false" android:state_pressed="false" /> </selector>
quelle
Sie können unsere Bibliothek ausprobieren: https://github.com/FutureMind/recycler-fast-scroll . Es befindet sich noch in der frühen Entwicklung, wurde jedoch speziell für Probleme mit der Glätte entwickelt, die wir bei anderen Bibliotheken hatten. Es verwendet einen etwas anderen Mechanismus. Es unterstützt auch horizontalen LayoutManager und wird in naher Zukunft auch mehrspaltige Setups unterstützen.
Bearbeiten: Es gibt jetzt einige nette Anpassungsoptionen.
quelle
Es ist vorgesehen, Bildlaufleisten mit
RecycleView
und zu implementierenLayoutManager
.Zum Beispiel:
computeVerticalScrollExtent()
,computeVerticalScrollOffset()
undcomputeVerticalScrollRange()
können Informationen liefern immer einen vertikalen Bildlauf Daumen an den richtigen Ort zu positionieren.Diese Methoden dienen auch
LayoutManager
zur Delegierung tatsächlicher Messungen. Die verwendeteLayoutManager
Implementierung muss diese Messungen unterstützen.Außerdem kann das Ziehen durch Berühren des Bildlaufdaumens durch Überschreiben
onInterceptTouchEvent()
von abgefangen werdenRecyclerView
. Und nach der Berechnung der gewünschten SchriftrollescrollTo()
kann zum Aktualisieren aufgerufen werdenRecyclerView
.quelle
Diese neue Bibliothek basiert auf dem schnellen Scroller von Framework Launcher: https://github.com/zhanghai/AndroidFastScroll
Verwendung :
new FastScrollerBuilder(recyclerView).build();
Optional
PopupTextProvider
im Adapter implementieren .quelle
Aktivieren Sie einfach das schnelle Scrollen und fügen Sie Daumen und Tracker für die Bildlaufleiste wie unten hinzu.
<android.support.v7.widget.RecyclerView android:id="@+id/rv_sensors" android:layout_width="match_parent" android:layout_height="match_parent" app:fastScrollEnabled="true" app:fastScrollHorizontalThumbDrawable="@drawable/thumb_drawable" app:fastScrollHorizontalTrackDrawable="@drawable/line_drawable" app:fastScrollVerticalThumbDrawable="@drawable/thumb_drawable" app:fastScrollVerticalTrackDrawable="@drawable/line_drawable" />
quelle
Der Fast-Scroller in Android Studio ist immer noch sehr fehlerhaft, da er nur auf XML basiert. Deshalb habe ich nach externen Bibliotheken gesucht, die schnelles Scrollen implementieren könnten. Sie können es hier bekommen . Sehr einfach zu implementieren und anzupassen.
quelle