JetpackComposeのmovableContentOf

Kenji Abe
4 min readApr 2, 2023

--

Photo by Mourizal Zativa on Unsplash

状態を保持したまま要素の配置を変更可能にする movableContentOf について紹介します。

movableContentOf の基本

まずは例として以下のように条件によって縦と横の並びを変更したいとします。

@Composable
fun MovableContentSample() {
// ...

if (vertical) {
Column {
Item()
Item()
}
} else {
Row {
Item()
Item()
}
}
}

@Composable
fun Item() {
// ...
}

このとき、条件が変わって ColumnRow が切り替わったときに中にある要素 Item はそれぞれCompositionが実行され、これまでの要素とは別物として扱われます。
そのため、Item の中で remember で保持している要素もすべて失われます。

これを movableContentOf を使って書き直して、配置が変更されても状態を保持できるようにします。

val movableContentItem1 = remember {
movableContentOf {
Item()
}
}

val movableContentItem2 = remember {
movableContentOf {
Item()
}
}

if (vertical) {
Column {
movableContentItem1()
movableContentItem2()
}
} else {
Row {
movableContentItem1()
movableContentItem2()
}
}

Composable関数を movableContentOf で囲むことによって、配置が変更されても同じものとして追跡できるので、状態が保持されたままになります。

パラメータを扱う

movableContentOf で使用するComposable関数にパラメータを渡したい場合は、以下のように型パラメータを指定することで可能になります。

val movableContentItem = remember {
movableContentOf<String> { text -> // Stringの型パラメータを指定
Item(text)
}
}

// ...
movableContentItem("hogehoge")

渡されるパラメータは最大で4つになります。

movableContentOf<Int, Int, Int, Int> { p1, p2, p3, p4 ->
// ...
}

Receiverを指定する

ColumnScope , RowScope のようなReceiverを指定することも出来ます。

val movableContentItem = remember {
movableContentWithReceiverOf<ColumnScope> {
// this は ColumnScopeになる
}
}

Column {
movableContentItem()
}

Receiverを指定した場合は、その対象のReceiver内から呼び出す必要があります。この例だと ColumnScope を指定した場合は Column 内から呼び出す必要があります。

参考

--

--

Kenji Abe
Kenji Abe

Written by Kenji Abe

Programmer / Gamer / Google Developers Expert for Android, Kotlin / @STAR_ZERO

No responses yet