Как добавить быстрый скроллер в RecyclerView
фон
в ListView у вас может быть быстрый скроллер, который позволяет вам перетаскивать полосу прокрутки, чтобы легко прокручивать ее туда, куда вы хотите (используя fastScrollEnabled)
вместе с " SectionIndexer" класс и, возможно, некоторые атрибуты, вы могли бы иметь хорошее всплывающее окно, которое показывает, как вы используете эту полосу прокрутки (link здесь).
такая вещь показана в приложении "Контакты", чтобы вы могли легко прокручивать определенные буквы.
проблема
RecyclerView, похоже, не имеет ни одного из них. Даже не быстрый свиток.
вопрос
Как добавить функцию быстрого скроллера для RecyclerView?
9 ответов:
я наткнулся на этот вопрос несколько дней назад, когда я столкнулся с этой ситуацией. Вот мой пример реализации FastScroll для RecyclerView:
github.com/danoz73/RecyclerViewFastScroller
попробуйте запустить пример приложения и просмотрите код, чтобы увидеть довольно простое использование простого виджета RecyclerViewFastScroller. Есть информация о github, но я включу основное использование здесь для вертикального быстрого скроллер.
полный пример см. В разделе пример приложения в репо.
Основное Использование
в действие или фрагмент XML, где находится RecyclerView, включите объект VerticalRecyclerViewFastScroller. Следующий пример будет в относительной компоновке:
... <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" /> ...в вашем фрагменте или деятельности, где вы устанавливаете макет программно, подключите быстрый скроллер к recycler:
... public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.recycler_view_frag, container, false); ... // Grab your RecyclerView and the RecyclerViewFastScroller from the layout RecyclerView recyclerView = (RecyclerView) rootView.findViewById(R.id.recyclerView); VerticalRecyclerViewFastScroller fastScroller = (VerticalRecyclerViewFastScroller) rootView.findViewById(R.id.fast_scroller); // Connect the recycler to the scroller (to let the scroller scroll the list) fastScroller.setRecyclerView(recyclerView); // Connect the scroller to the recycler (to let the recycler scroll the scroller's handle) recyclerView.setOnScrollListener(fastScroller.getOnScrollListener()); ... return rootView; } ...Надежда это помогает!
EDIT: теперь добавлена поддержка Android-Lollipop-контакты-индикаторы раздела стиля! Проверьте пример реализации приложения для деталей.
поскольку все сторонние библиотеки имели проблемы, я решил собрать то, что я могу найти (в основном от здесь), исправьте все и опубликуйте мой собственный POC быстрого скроллера RecyclerView:
https://github.com/AndroidDeveloperLB/LollipopContactsRecyclerViewFastScroller
использование:
сделать RecyclerView.Адаптер, реализующий BubbleTextGetter, которому задана позиция в данных возвращает текст, чтобы показать в пузырь-всплывающее окно.
поместите FastScroller внутри макета, который содержит RecyclerView (вероятно, в нужной области).
настройка FastScroller FastScroller
недостатки:
- не поддерживает изменение ориентации, но это, вероятно, легко исправить.
- не поддерживает другие layoutManagers. Только LinearLayoutManager
- требуется API 11 и выше.
код:
BubbleTextGetter
public interface BubbleTextGetter { String getTextToShowInBubble(int pos); }ресайклер_вид_быстро_скроллер__быстро_скроллер.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>MainActivity
... fastScroller=(FastScroller)findViewById(R.id.fastscroller); fastScroller.setRecyclerView(recyclerView);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); } } }
есть много вопросов без ответов о
RecyclerViewи fast-scroll / section indexer давайте попробуем, чтобы перегруппироваться и собрать наши мнения и информацию здесь.короткий ответ:нет, вы не можете включить быструю прокрутку, потому что RecyclerView не содержит FastScroller объект и никакие связанные переменные логического состояния. Это потому что
RecyclerViewне AbsListView.С другой стороны, это не невозможно реализовать
RecyclerView, который содержит свалил версияFastScrollerи необходимая логика для быстрой прокрутки, но я не видел никакой реализации этого до сих пор.пожалуйста, поделитесь своим мнением об этом, или если вы думаете, что я ошибаюсь.
библиотека поддержки Android 26.0.0 теперь поддерживает
fastScrollEnabledновый логический флаг fastScrollEnabled для RecyclerView.
если включено, то должны быть установлены fastScrollHorizontalThumbDrawable, fastScrollHorizontalTrackDrawable, fastScrollVerticalThumbDrawable и fastScrollVerticalTrackDrawable.
образец -https://android.jlelse.eu/fast-scrolling-with-recyclerview-2b89d4574688
вы также можете использовать A-Z Fastscroll для RecyclerView. Это стиль iOS.
https://github.com/code-computerlove/FastScrollRecyclerView/
как использовать:
- заменить
android.support.v7.widget.RecyclerViewсcom.codecomputerlove.fastscrollrecyclerviewdemo.FastScrollRecyclerView- ваш адаптер должен реализовать FastScrollRecyclerViewInterface и переопределить
getMapIndex(). Функция должна возвращать mapIndex. Посмотрите вcalculateIndexesForName()для вдохновения о том, как создать его. После создания передать его адаптер в конструкторе.- создать экземпляр
FastScrollRecyclerViewItemDecorationи добавить его на RecyclerViewFastScrollRecyclerViewItemDecoration decoration = new FastScrollRecyclerViewItemDecoration(this); mRecyclerView.addItemDecoration(decoration);- добавить
<dimen name="fast_scroll_overlay_text_size">100dp</dimen>в свой . Это размер dp наложенной буквы
вы можете попробовать наш lib:https://github.com/FutureMind/recycler-fast-scroll. он все еще находится в ранней разработке, но был построен специально для решения проблемы гладкости, которую мы испытали с другими библиотеками. Он использует немного другой механизм. Он также поддерживает горизонтальный LayoutManager, а также будет поддерживать многоколоночные настройки в ближайшем будущем.
Edit: теперь есть несколько аккуратных вариантов настройки.
функциональность FastScroller добавлена из библиотеки android 26.0.0 для RecyclerView
компиляции зависимостей
compile 'com.android.support:recyclerview-v7:26.1.0' compile 'com.android.support:design:26.1.0'добавить depedency в проект.gradle
maven { url "https://maven.google.com" }ваш recyclerview.xml-файл
<?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>большой палец.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>линии.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>
существует положение реализации полос прокрутки с
RecycleViewиLayoutManager.например:
computeVerticalScrollExtent(),computeVerticalScrollOffset()иcomputeVerticalScrollRange()может предоставить информацию всегда располагать вертикальный ползунок на нужное место.эти методы также есть в
LayoutManagerдля передачи фактических измерений. Так чтоLayoutManagerреализация должна поддерживать эти измерения.кроме того, перетащить прикосновение на прокрутку пальца можно перехватить путем переопределения
onInterceptTouchEvent()наRecyclerView. И после вычисления нужного свитка,scrollTo()для обновленияRecyclerView.
просто включите быструю прокрутку и добавьте большой палец, трекер для полосы прокрутки, как показано ниже.
<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" />
Comments