Jetpack Compose 0.1.0-dev05がリリースされましたね。0.1.0-dev05でui-foundationにAdapterList
というComposableが追加されました。
待望のAdapterList
AdapterListの説明は次のようになっています。
A vertically scrolling list that only composes and lays out the currently visible items.
今まではRecyclerViewのようなComposableが存在せず、VerticalScrollerを使ってそれっぽい動作をしていましたが、VerticalScrollerはScrollViewと同じものなので実用には限界がありました。
AdapterListはRecyclerViewと同じように、表示されている要素だけをレンダリングするので、大量の要素があってもサクサク動作します。
AdapterListの使い方
AdapterListのシグネチャは次の通りです。
@Composable fun <T> AdapterList( data: List<T>, modifier: Modifier = Modifier.None, itemCallback: @Composable() (T) -> Unit )
実際に使うには次のようになります。
import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import androidx.ui.core.Text import androidx.ui.core.setContent import androidx.ui.foundation.AdapterList import androidx.ui.layout.Container import androidx.ui.layout.LayoutPadding import androidx.ui.layout.LayoutWidth import androidx.ui.material.MaterialTheme import androidx.ui.material.surface.Card import androidx.ui.unit.dp class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { MaterialTheme { val data = 0.until(100).toList() AdapterList(data = data) { Card(modifier = LayoutPadding(top = 8.dp, bottom = 8.dp, left = 16.dp, right = 16.dp)) { Container(modifier = LayoutWidth.Fill + LayoutPadding(16.dp)) { Text("Hello ${it}") } } } } } } }
AdapterListはまだ実用できない
0.1.0-dev05の時点ではまだ2コミットしかないので、実用に足らないのは当然っちゃ当然かなと思います。 https://android.googlesource.com/platform/frameworks/support/+log/refs/heads/androidx-compose-release/ui/ui-foundation/src/main/java/androidx/ui/foundation/AdapterList.kt
具体的な問題としては 要素のクリックイベントが動作しない
という点があります。例えば次のコードのButtonはうまく動作しません。
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { MaterialTheme { val data = 0.until(100).toList() AdapterList(data = data) { value -> Card(modifier = LayoutPadding(top = 8.dp, bottom = 8.dp, left = 16.dp, right = 16.dp)) { Container(modifier = LayoutWidth.Fill + LayoutPadding(16.dp)) { Button(onClick = { println("click! $value") }) { Text("button ${value}") } } } } } } } }
いくらか実験してみたところ、Ripple要素があるとクリックイベントが実行されないようです。Buttonは Ripple + Clickableで構成されているので反応しなくなっているようです。Rippleを使わずClickableのみを使えば動作はするのですが、タッチフィードバックがなくなるので厳しいです。
もちろんこうした問題は今後どんどん改善されていくと思いますが、今すぐに使うというのはちょっと難しそうです。
おわりに
ついにAdapterListが登場して実用段階への光が射してきましたね。さすがにプロダクション投入はまだまだ難しいですが、一部のViewをComposeに置き換えるのは十分できそうだなぁと思います。