RecyclerViewでFastScroll

ListViewやGridView（つまりAbsListView）なら、レイアウトXMLで以下のように書くだけで実現できた。

```xml
<ListView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:fastScrollEnabled="true" />
```

RecyclerViewではこれができない、という状況が長く続いていた。
ライブラリを導入しようにも、決定版になるようなものは出ていなかった（個人の感想）。

……と思っていたのだが、久しぶりに調べてみたところ、Support Library 26でAPIが追加されたとのこと。
https://developer.android.com/topic/libraries/support-library/revisions.html#26-0-0
> New fastScrollEnabled boolean flag for RecyclerView. If enabled, fastScrollHorizontalThumbDrawable, fastScrollHorizontalTrackDrawable, fastScrollVerticalThumbDrawable, and fastScrollVerticalTrackDrawable must be set.


## 動作イメージ

<img src="https://qiita-image-store.s3.amazonaws.com/0/24654/0ef3ef33-388b-46bf-f820-87ad74086750.gif" width="270">

サンプルコードの実装抜粋  
https://gist.github.com/75py/3b510a511d3d3231bc409e5517207818


## 設定方法

### Layout XML

```activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/recyclerView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:fastScrollEnabled="true"
    app:fastScrollHorizontalThumbDrawable="@drawable/fast_scroll_thumb"
    app:fastScrollHorizontalTrackDrawable="@drawable/fast_scroll_track"
    app:fastScrollVerticalThumbDrawable="@drawable/fast_scroll_thumb"
    app:fastScrollVerticalTrackDrawable="@drawable/fast_scroll_track" />
```
* ```android:fastScrollAlwaysVisible```のような細かい指定はできないので、AbsListViewと完全に同等のことができる、というわけではなさそう。
* 縦横どちらかにしかスクロールしない場合でも、Vertical/Horizontal両方の指定が必要（いずれかが欠けていると例外がスローされる）

> java.lang.IllegalArgumentException: Trying to set fast scroller without both required drawables.

### Drawable XML

基本的には、これだけで良い。  

```fast_scroll_thumb.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true">
        <shape android:shape="rectangle">
            <solid android:color="#f00" />
        </shape>
    </item>
    <item>
        <shape android:shape="rectangle">
            <solid android:color="#00f" />
        </shape>
    </item>
</selector>
```

```fast_scroll_track.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <solid android:color="#0f0" />
</shape>
```

個人的には、trackの方は透明でいいと思う。

```fast_scroll_track_transparent.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <solid android:color="@android:color/transparent" />
</shape>
```

### Drawable XML（改善案 API23以降）

↑だと触れる範囲が非常に小さいので、正直言って使いづらい。  
ソースを覗く限り、そのうち margin みたいな値が指定できるようになりそうだが、とりあえず Drawable を工夫してあげると、触れる範囲を広げることができる。  
以下の例では、ツマミ8dpの左側40dpも触れるようにしてみた。
*【2018/1/24追記】以下の例だと、API22以下でツマミの幅が48dpになってしまう。（自分のアプリはminSdkVersion=24にしているから気付かなかった）*

```fast_scroll_thumb2.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true">
        <layer-list>
            <item android:gravity="end">
                <shape android:shape="rectangle">
                    <solid android:color="#f00" />
                    <size android:width="8dp" />
                </shape>
            </item>
            <item>
                <shape android:shape="rectangle">
                    <solid android:color="@android:color/transparent" />
                    <size android:width="48dp" />
                </shape>
            </item>
        </layer-list>
    </item>
    <item>
        <layer-list>
            <item android:gravity="end">
                <shape android:shape="rectangle">
                    <solid android:color="#00f" />
                    <size android:width="8dp" />
                </shape>
            </item>
            <item>
                <shape android:shape="rectangle">
                    <solid android:color="@android:color/transparent" />
                    <size android:width="48dp" />
                </shape>
            </item>
        </layer-list>
    </item>
</selector>
```

### Drawable XML（改善案その２）

　前述の例だと、API22以下でツマミの幅が48dpになってしまう。
（API22-23の間にXMLの解釈方法が変わっているようだが、どういう理屈かまでは追っていない）
変更点は「gravity → left」のみ。。

```fast_scroll_thumb3.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true">
        <layer-list>
            <item android:left="40dp">
                <shape android:shape="rectangle">
                    <solid android:color="#f00" />
                    <size android:width="8dp" />
                </shape>
            </item>
            <item>
                <shape android:shape="rectangle">
                    <solid android:color="@android:color/transparent" />
                    <size android:width="48dp" />
                </shape>
            </item>
        </layer-list>
    </item>
    <item>
        <layer-list>
            <item android:left="40dp">
                <shape android:shape="rectangle">
                    <solid android:color="#00f" />
                    <size android:width="8dp" />
                </shape>
            </item>
            <item>
                <shape android:shape="rectangle">
                    <solid android:color="@android:color/transparent" />
                    <size android:width="48dp" />
                </shape>
            </item>
        </layer-list>
    </item>
</selector>
```