Androidの用途別GridViewライブラリのすゝめ

# 概要
画像などの情報をタイル上に並べてくれる便利なウィジェットのGridView。

しかし標準で用意されているものだと何かと機能が足りない事があって困った人は多いんじゃないだろうか。

例えば

- ListViewにあったaddHeaderViewやaddFooterViewがサポートされていない
- カラムの高さが列ごとに整理されてしまう。そのため列のカラム同士の高さがバラバラな場合に低いカラムの下に余白が空いてしまう
- カラムの幅が固定されてしまう。なのである列は二列、ある列は四列みたいな柔軟な表示ができない

そこで今回は用途別に使えるGridViewのライブラリを個人的な感想も含めて(使っていれば)まとめてみることにした。

# ListViewのようなaddHeaderViewやaddFooterViewが欲しい！
## HeaderGridView
com.google.androidパッケージで一応HeaderViewが追加できるものが存在していたりする

しかしFooterViewが追加できないのでFooterにViewを追加したい人は別のライブラリ使うのが良いかも

> http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android-apps/4.3.1_r1/com/android/photos/views/HeaderGridView.java

## HeaderFooterGridView
Recruit Marketing Partnersが出しているGridViewのライブラリ
記事執筆時点ではつい最近公開されたライブラリっぽい

名前の通りHeaderViewとFooterViewの両方が追加できるのが便利。

この会社で作られているアプリの「料理サプリ」でも使われているらしいのである程度安定感もありそう

軽く使ってみた感じだと動作に問題はなさそうだった

> https://github.com/recruit-mp/android-HeaderFooterGridView [Github]
> http://tech.recruit-mp.co.jp/mobile/android-headerfootergridview/ [Blog]

## AbsListViewHelper
個人的に特に問題なければこの解決方法が汎用性もあってベストではという気がしなくもない

上の二つのライブラリと違って、AbsListViewHelperというクラスにAbsListViewを継承しているクラスのインスタンスを渡してHelper経由でHeaderViewとFooterViewをセットできる

GridViewはAbsListViewを継承しているので使える

この仕組みによって、気に入ったGridViewライブラリが仮にaddHeaderViewとaddFooterViewをサポートしてなかった場合でも、そのライブラリがAbsListViewを継承したクラスであればこのライブラリ経由でViewを追加できるので選択の幅が広がる

Gradleサポートされているのもいい感じ

![demo.gif](https://qiita-image-store.s3.amazonaws.com/0/20629/fb744622-a5d3-7bdc-f933-ce53d40b36dc.gif)

> https://github.com/felipecsl/AbsListViewHelper

# 高さがバラバラのカラムを綺麗に表示させたい！
## AndroidStaggeredGrid
多分この用途のライブラリの中では一番有名かもしれない

標準のGridViewを扱うような感じでListAdapterに高さの違うViewを返しても、このライブラリがうまくカラム高さを計算していい感じに均等に配置してくれるというスグレモノのGridView

Gradleサポートされているので導入が簡単で、Etsyのアプリで使われているものが公開されている

### 気になったところ
最近良く使うライブラリなので、細かい部分の問題も書いておく

#### SwipeRefreshLayoutと相性が悪い？
- 高速スクロールしてると、リストの途中なのにStaggeredGridViewに引っかかって(?)スワイプ更新が走ったりすることがある
- ViewPagerの中にあるFragment内で描画してたので、それも関係あるのかもしれない

#### スクロールが表示されない
- サポートされてないっぽい
- 高速スクロールも同じくできない

#### setSelectionがサポートされていない
- 指定したpositionの項目に移動させる事ができない
- 一応この方法でできるけど、微妙に上 or 下にズレたり正確な位置に移動できない時がある
 - https://github.com/etsy/AndroidStaggeredGrid/issues/135

![687474703a2f2f662e636c2e6c792f6974656d732f327a31423059304d3047304f326b316c334a30332f5472656e64696e672e706e67.png](https://qiita-image-store.s3.amazonaws.com/0/20629/599b6d7d-03a5-01b2-0c28-a320ee6477bc.png)

> https://github.com/etsy/AndroidStaggeredGrid

## StaggeredGridView
com.google.androidパッケージでも一応それっぽいことができるコードが存在する

SwipeRefreshLayoutと相性が悪い？AndroidStaggeredGridと同じ症状が高頻度で発生するので使いづらかった
SwipeRefreshLayoutと組み合わせなければ割りと動くんだろうか

> http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.2.1_r1.2/com/android/ex/widget/StaggeredGridView.java

これをベースにして修正を加えたのがこのライブラリ

> https://github.com/maurycyw/StaggeredGridView

## StaggeredGridView(その2)
これも同じようなことができるみたいなんだけど検証不足なので詳しい説明はなし

カラムの高さが固定されてるならfix、高さが不定ならdynamicでうまくモードを切り替えて使えるっぽい

上２つがうまく動かなかったら試してみるといいかも

> https://github.com/smanikandan14/StaggeredGridView

# カラムの幅を自由に設定して表示させたい！
## AsymmetricGridView
こういったViewを使ったアプリを作る機会がなく、動作を試していないので詳しい説明はなし

初めにカラム数を指定したあと、項目毎に表示領域のカラム数と列数を指定するとライブラリ側でうまいこと調整して表示してくれる

使い方は他のAbsListViewタイプと同じような感じでAsymmetricGridViewAdapterにあるgetActualViewメソッドをオーバーライドして表示するViewをカスタマイズできそう

![ss_5_cols.png](https://qiita-image-store.s3.amazonaws.com/0/20629/411434d7-0825-9b12-e6c1-e8b82ac4ae23.png)

> https://github.com/felipecsl/AsymmetricGridView

## FreeFlow
これも使ったことがないので詳しい説明はなし

こちらは動的カラムを変更した時でもアニメーションして変更を反映してくれるみたい

> https://github.com/Comcast/FreeFlow

## Parchment
使ったことなくてどこまでできるのかもあんまり把握してないけど、こういうライブラリもあったよって感じで紹介

![68747470733a2f2f692e696d6775722e636f6d2f3241724f6c747a2e706e67.png](https://qiita-image-store.s3.amazonaws.com/0/20629/02fea173-6b37-ee86-fe88-9c5235f022cf.png)

> https://github.com/EmirWeb/parchment

# セクションで隔てたい！
## StickyGridHeaders
StickyListHeadersのGridView版

下のgifのような感じに追従するセクションヘッダーを実装することができる便利ライブラリ

導入が簡単で非常に使いやすい

- mavenrepositoryに上がってるので、maven, gradleから入れられる
- StickyGridHeadersBaseAdapterを既存のAdapterにimplementして、必要な情報を返すようにすると後はライブラリがいい感じに表示してくれる

![demo (1).gif](https://qiita-image-store.s3.amazonaws.com/0/20629/5d14ea41-e89b-b8db-26da-6e0dc2884a6d.gif)
(これはStickyListHeadersの画像だが、これのGridView版と考えてよい)

> https://github.com/TonicArtos/StickyGridHeaders

# 横スクロールさせたい！
## TwoWayGridView
スクロール方向を指定できるGridViewライブラリ

端末の向きによってスクロール方向が指定できるの地味に便利だと思う
例えば縦向きの時は縦スクロール、横向きの時は横スクロールみたいにしてスクリーンの幅を活かした操作性を提供できそう

> https://github.com/jess-anders/two-way-gridview

# ドラッグで移動させたい！
## DynamicGrid
これは使ったことがないので細かい説明はなし

デモ動画だとホーム画面みたいに長押しでドラッグアンドドロップしているけど、DynamicGridViewのstartEditModeとstopEditModeで状態を管理しているみたいなので、特定の動作の時に編集モードにするといった事ができそう

setOnDropListenerでドロップ時のイベントが拾えるみたいだけど、ドラッグしたアイテムが最終的にどの位置に置かれたかは自分で何らかの方法で取ってこないとだめっぽい

> https://github.com/askerov/DynamicGrid

# あとがき
GridViewのライブラリは他にも一杯あるので、興味のある人は色々調べてみるといいかも