リストビューでは、スクロールバーをドラッグして希望する場所に簡単にスクロールできる高速スクローラーを使用できます( fastScrollEnabled =属性)
「 SectionIndexer 」クラスおよびオプションでいくつかの属性と一緒に、このスクロールバーを使用すると表示されるニースポップアップを作成できます(リンク herehere ).
このようなことが連絡先アプリに表示されるため、特定の文字に簡単にスクロールできます。
RecyclerViewにはこれらのいずれも含まれていないようです。高速スクロールでさえありません。
RecyclerViewに高速スクローラー機能を追加するにはどうすればよいですか?
すべてのサードパーティライブラリに問題があるため、見つけることができるものを収集することにしました(主に here )、修正すべて、RecyclerViewの高速スクローラーのPOCを公開します。
https://github.com/AndroidDeveloperLB/LollipopContactsRecyclerViewFastScroller
使用法:
bubbleTextGetterを実装するRecyclerView.Adapterを作成します。これは、データ内の位置を指定すると、バブルポップアップに表示するテキストを返します。
fastScrollerをRecyclerViewを収容するレイアウト内に配置します(おそらく右側の領域)。
FastScroller FastScrollerをカスタマイズする
いくつかの欠点:
コード:
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>
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のFastScrollの実装例:
サンプルアプリケーションを実行してみて、コードを熟読して、単純なRecyclerViewFastScrollerウィジェットのかなり単純な使用法を確認してください。 githubには情報がありますが、ここでは垂直高速スクローラーの基本的な使用法を説明します。
完全な例については、 リポジトリ内のサンプルアプリケーション を参照してください。
RecyclerViewが存在するアクティビティまたはフラグメントXMLに、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"
/>
...
プログラムでレイアウトを設定するフラグメントまたはアクティビティで、高速スクローラーをリサイクラに接続します。
...
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-Contacts-styleセクションインジケーターのサポートが追加されました! サンプルアプリケーションの実装の詳細を確認してください。
RecyclerView
およびfast-scroll/section indexerに関する未回答の質問が多数あります。ここで意見や情報を再グループ化して収集してみましょう。 。
短い答えは:いいえ、高速スクロールを有効にすることはできませんRecyclerView には FastScroller オブジェクトおよび関連する論理状態変数。これは、RecyclerView
が AbsListView ではないためです。
一方、RecyclerView
のダンプバージョンと高速スクロールに必要なロジックを含むFastScroller
を実装することは不可能ではありませんが、これまでのところ実装は見ていません。
それについて、またはあなたが私が間違っていると思うなら、あなたの考慮を共有してください。
Android Support Library 26.0.0はfastScrollEnabled
をサポートするようになりました
RecyclerViewの新しいfastScrollEnabledブール値フラグ。
有効にした場合、fastScrollHorizontalThumbDrawable、fastScrollHorizontalTrackDrawable、fastScrollVerticalThumbDrawable、およびfastScrollVerticalTrackDrawableを設定する必要があります。
サンプル- https://Android.jlelse.eu/fast-scrolling-with-recyclerview-2b89d4574688
RecyclerViewにはA-Z Fastscrollも使用できます。 iOSスタイルです。
https://github.com/code-computerlove/FastScrollRecyclerView/
それを使用する方法:
Android.support.v7.widget.RecyclerView
をcom.codecomputerlove.fastscrollrecyclerviewdemo.FastScrollRecyclerView
に置き換えますgetMapIndex()
をオーバーライドする必要があります。関数はmapIndexを返す必要があります。 calculateIndexesForName()
を調べて、作成方法のヒントを得てください。作成したら、コンストラクタでアダプタに渡します。FastScrollRecyclerViewItemDecoration
のインスタンスを作成し、RecyclerView FastScrollRecyclerViewItemDecoration decoration = new FastScrollRecyclerViewItemDecoration(this); mRecyclerView.addItemDecoration(decoration);
に追加します<dimen name="fast_scroll_overlay_text_size">100dp</dimen>
を/values/dimens.xml
ファイルに追加します。これは、オーバーレイされた文字のdpサイズですFastScroller機能は、RecyclerViewのAndroidライブラリ26.0.0から追加されます
コンパイルの依存関係
compile 'com.Android.support:recyclerview-v7:26.1.0'
compile 'com.Android.support:design:26.1.0'
project.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>
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>
Lib: https://github.com/FutureMind/recycler-fast-scroll を試すことができます。まだ初期の開発段階ですが、他のライブラリで経験したスムーズさの問題に対処するために特別に構築されました。少し異なるメカニズムを使用します。水平LayoutManagerもサポートし、近い将来、複数列のセットアップもサポートします。
編集:いくつかのきちんとしたカスタマイズオプションがあります。
RecycleView
とそのLayoutManager
でスクロールバーを実装する規定があります。
たとえば、 computeVerticalScrollExtent()
、 computeVerticalScrollOffset()
および computeVerticalScrollRange()
は、常に正しい位置に垂直スクロールつまみを配置するための情報を提供できます。
これらのメソッドは、実際の測定値を委任するための LayoutManager
にもあります。したがって、使用されるLayoutManager
実装はこれらの測定をサポートする必要があります。
また、スクロール変数のドラッグタッチは、RecyclerView
の onInterceptTouchEvent()
をオーバーライドすることでインターセプトできます。目的のスクロールを計算した後、 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" />