要素の高さがバラバラのRecyclerViewを使う(Pinterest的レイアウト)

#某有名画像サイトのように要素を表示したい!

><img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520167/bc7cd1a4-6a69-af26-5faf-a2fa43cf9b3d.jpeg"/>
>Pinterestアンドロイドアプリより

こういう高さがそれぞれの要素のwrapになってるやつをやってみたかった。

#今回作るもの
これ↓
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520167/760bedf8-b099-713b-bb7d-5f7d0914d0b5.jpeg"/>

少しわかりづらいがimageの高さに合わせて要素が積み重なっている。
画像はLolem Picsumのものを表示


#結論
先に結論からいくと、**RecyclerViewのレイアウトマネージャーをStaggeredGridLayoutManager**にするだけで出来る。


```kotlin
val layoutManager = StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL)
recyclerView.adapter = adapter
recyclerView.layoutManager = layoutManager
```

LinearLayoutとかGridLayoutとかはよく使うけどStaggeredGridLayoutManagerはあんまり聞いたことないし、単語の意味も知らなかったから使ったことなかったが、実はすごく便利だった。(ちなみにstaggerは「よろめく」とかいう意味らしい)

###引数
```
StaggeredGridLayoutManager(一行に表示する要素の数, recyclerViewの方向(縦向きか横向きか))
```

一応recyclerViewをあんまり使ったことのない方向けにrecyclerViewの実装コードも以下に掲載しておきます。

#全コード
RecyclerViewを普通に実装していくだけなのでコードだけ載せます。解説等は他の方の記事にもたくさん載っていますので必要な方は探してみてください。

作るファイルは以下の通り

| ファイル名| 内容|
|:-----------------|:-----------------:|
| MainActivity.kt|recyclerViewの実装|
| Adapter.kt|recyclerViewのアダプタ|
| activity_main.xml|recyclerViewを置くレイアウトファイル|
| item.xml|recyclerViewの中身のレイアウトファイル

##依存関係とパーミッション
URL画像を表示するためにピカソ

```gradle:build.gradle
    implementation 'androidx.recyclerview:recyclerview:1.1.0'
    implementation 'com.squareup.picasso:picasso:2.3.3'
```

ネットの画像を表示するためにインターネットパーミッション
マニフェストに追加

```xml:AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
```



##activity_main.xml
先にレイアウトファイルから

```xml:activity_main.xml
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
```

##item.xml
ImageViewのところが赤く表示されるかもしれませんが今回のやつには関係ないので無視して大丈夫です。
**ImageViewのheightはwrap_contentに注意**

```xml:item.xml
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <ImageView
        android:id="@+id/img"
        android:layout_width="170dp"
        android:layout_height="wrap_content"
        android:adjustViewBounds="true"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@drawable/ic_launcher_background" />
</androidx.constraintlayout.widget.ConstraintLayout>
```

##Adapter.kt
続いてアダプタ

```kotlin:Adapter.kt

class Adapter(private val context: Context, private val urlList: ArrayList<String>) :
    RecyclerView.Adapter<RecyclerView.ViewHolder>() {

    class ImgViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        val img = view.img
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        val inflater = LayoutInflater.from(parent.context)
        val item = inflater.inflate(R.layout.item, parent, false)
        return ImgViewHolder(item)
    }

    override fun getItemCount(): Int {
        return urlList.size
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        // Picassoを使ってURLの画像を読み込む
        Picasso.with(context).load(urlList[position]).into(holder.itemView.img)
    }
}
```

##MainActivity.kt
最後にrecyclerViewを実装しておわり

```kotlin:MainActivity.kt

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val urlList = arrayListOf<String>()
        // Lolem Picsumの縦横ランダムな大きさの画像のURLを取得する
        for(i in 0..17){
            val index = (100..800).random()
            val width = (250..600).random()
            val height = (150..600).random()
            urlList.add("https://i.picsum.photos/id/$index/$width/$height.jpg")
        }
        //アダプタとレイアウトマネージャーをセット
        val adapter = Adapter(this, urlList)
        val layoutManager = StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL)
        recyclerView.adapter = adapter
        recyclerView.layoutManager = layoutManager
    }
}
```
いやぁ、Lorem Picsum便利。
完成！！