Как добавить быстрый скроллер в RecyclerView



фон



в ListView у вас может быть быстрый скроллер, который позволяет вам перетаскивать полосу прокрутки, чтобы легко прокручивать ее туда, куда вы хотите (используя fastScrollEnabled)



вместе с " SectionIndexer" класс и, возможно, некоторые атрибуты, вы могли бы иметь хорошее всплывающее окно, которое показывает, как вы используете эту полосу прокрутки (link здесь).



такая вещь показана в приложении "Контакты", чтобы вы могли легко прокручивать определенные буквы.



проблема



RecyclerView, похоже, не имеет ни одного из них. Даже не быстрый свиток.



вопрос



Как добавить функцию быстрого скроллера для RecyclerView?

723   9  

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

использование:

  1. сделать RecyclerView.Адаптер, реализующий BubbleTextGetter, которому задана позиция в данных возвращает текст, чтобы показать в пузырь-всплывающее окно.

  2. поместите FastScroller внутри макета, который содержит RecyclerView (вероятно, в нужной области).

  3. настройка FastScroller FastScroller

недостатки:

  1. не поддерживает изменение ориентации, но это, вероятно, легко исправить.
  2. не поддерживает другие layoutManagers. Только LinearLayoutManager
  3. требуется 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 и добавить его на RecyclerView FastScrollRecyclerViewItemDecoration 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

    Ничего не найдено.