注意!
この記事はQiitaにて公開されていた内容をimportしたものです。
これらの内容は場合によっては陳腐化していて役に立たなくなっていたり、有害であったり、現在の著者の主張と異なることがあります。
皆様の判断の上でご利用いただけますと幸いです(度を超してヤバいものは著者に連絡して頂ければ対応します m(_ _)m)
【注意!】
recyclerview-v7:23.4.0
あたりから、RecyclerViewにwrap_content
を使った時の挙動が変わっていることに気が付きました。
まだ調査中ですが、「高さ=アイテム個数ぶんの高さ」ではなくなっているように感じられます。
以下の記事はrecyclerview-v7:23.2.1
で執筆しています。その点をご理解いただきますようお願い致します。
本記事を読む前に
以下の記事・資料をご確認ください。
- Google Developers Japan: Android Support Library 23.2 を公開
- Support Library v23.2 overview // Speaker Deck
Support Library 23.2 でRecyclerViewに変更が!
Android Support Library 23.2 において、RecyclerViewのwidth/height属性に"wrap_content"を指定できるようになりました!
厳密には “RecyclerView.LayoutManager no longer ignores some RecyclerView.LayoutParams settings” とのこと。
・・・ところで、“wrap_content"が指定できるようになると、どのような意味があるのでしょうか? 実際にサンプルプログラムを書いて検証してみました。
サンプルコードはこちら
無駄にKotlinを使ったりしておりますが、重要なのはlayoutファイルなので、Kotlin分からなくても問題無いです(というかあんまりKotlinらしく書けてない気はする)
検証方法
以下の3種類のlayoutにおいて、LinearLayoutManagerを使ったRecyclerViewのアイテム数でどのような変化があるのかを調べました。
- RecyclerViewのheightに"match_parent"を指定した場合
- (activity_match_parent.xml)
- RecyclerViewのheightに"wrap_content"を指定した場合
- (activity_wrap_content.xml)
- RecyclerViewのheightに"wrap_content"を指定しつつ、ScrollView+LinearLayoutで包んだ場合
- (activity_wrap_content_with_scrollview.xml)
わかりやすくするために、RecyclerViewの背景をピンクにしてあります。あとリストアイテムにも極端なカラーリングを施してあります。
検証1: アイテム数が0件のとき
match_parent | wrap_content | wrap_content(+RecyclerView) |
match_parentはおなじみですね。たとえアイテム数が0件でも、画面全体を覆うことが分かります。オーバースクロールエフェクトも表示されている、ということも割と重要な点かも知れません。
wrap_contentは、アイテム数が0件だと高さが0になるため、RecyclerViewは存在してないかのように見えます。
検証2: アイテム数が1件のとき
match_parent | wrap_content | wrap_content(+RecyclerView) |
興味深いことに、ここでは3種類とも異なる結果となりました。
match_parentでは、画面全体にリストが1件ポツンとあります。
wrap_contentでは、リストが1件だけあり、RecyclerViewはアイテム1つぶんの高さのみ確保されています。そしてオーバースクロールエフェクトが表示されているのも重要です(がこれはandroid:overScrollMode="never"
で消せます)。
ScrollViewでラップしたRecyclerViewでも単なるwrap_contentと表示は似ています。ただしオーバースクロールエフェクトが表示されていません。これを踏まえた上で次にいってみましょう。
検証3: アイテム数が50件のとき
match_parent | wrap_content | wrap_content(+RecyclerView) |
ここで面白いのは、画面に収まらないくらい件数があるときはmatch_parentとwrap_contentが同じ見た目・動作をしているということです。
更に面白いのは、ScrollViewでラップしたRecyclerViewでは、(ScrollViewの初回表示座標がヘンなのは惜しいのだけど)画面全体をスクロールさせることができます。 これまで、このような表現を実現させたくば、RecyclerAdapterでviewTypeを使うなどする必要があったので、とても驚きです!でもね・・・
ScrollViewでラップしたRecyclerViewで注意すべきこと
RecyclerViewの「Viewの使い回し」が機能しなくなる
常識な話だとは思いますが、ListViewやRecyclerViewは、Viewの使い回しを行うことで端末資源の使用量の削減をしています。
一方で、RecyclerViewの寸法がアイテム数によって変わるということは、すべてのアイテムをRecyclerViewの領域にレンダリングすることになるため、アイテム数が50件だろうが100件だろうが表示されてしまいます。
これは実際にRecyclerAdapterにログを仕込んで確認すると分かりますが、いきなり件数分のonBindViewHolder
が呼ばれます。
よって、常識外の件数を放り込めばまずいことになります(低メモリ端末だと常識内の件数でもまずいことになりそう)。
ScrollViewと組み合わせると、何故かRecyclerViewの上部までスクロールされる問題
ちょっと触れましたが、ScrollViewが予期せぬ位置から開始するのが気になります。 ちょっとなんとかしようと頑張ったのですが、うまくいきませんでした。
なめらかにスクロールしない
慣性をもったスクロールが機能しなくなります。さっき動画撮影をしていて気が付きました。ううむ。。
ぶっちゃけ使いどころはどこなのか?
まぁ難しいのですが、画面内の途中に唐突に0件から数件(数は場合によりけり不定)のアイテムを表示するUI実装は楽になるのかなぁ、と思います。
まとめ
ちょっとクセのある新機能ですが、もしかしたらとても便利な使い方が今後出てくる・・・かも?