状態を保持したまま要素の配置を変更可能にする movableContentOf
について紹介します。
movableContentOf の基本
まずは例として以下のように条件によって縦と横の並びを変更したいとします。
@Composable
fun MovableContentSample() {
// ...
if (vertical) {
Column {
Item()
Item()
}
} else {
Row {
Item()
Item()
}
}
}
@Composable
fun Item() {
// ...
}
このとき、条件が変わって Column
と Row
が切り替わったときに中にある要素 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
内から呼び出す必要があります。