Compose UI に Android View 階層を含めることができます。このアプローチは特に、Compose でまだ利用できない UI 要素(AdView
など)を使用する場合に便利です。このアプローチでは、設計したカスタムビューを再利用することもできます。
ビュー要素または階層を含めるには、AndroidView
コンポーザブルを使用します。AndroidView
には、View
を返すラムダが渡されます。AndroidView
には、ビューがインフレートされるときに呼び出される update
コールバックも用意されています。AndroidView
は、コールバック内で読み込まれた State
が変更されるたびに、再コンポーズを行います。AndroidView
は、他の多くの組み込みコンポーザブルと同様に、Modifier
パラメータを受け取ります。これは親コンポーザブルでの位置を設定したりするために使用できます。
@Composable fun CustomView() { var selectedItem by remember { mutableStateOf(0) } // Adds view to Compose AndroidView( modifier = Modifier.fillMaxSize(), // Occupy the max size in the Compose UI tree factory = { context -> // Creates view MyView(context).apply { // Sets up listeners for View -> Compose communication setOnClickListener { selectedItem = 1 } } }, update = { view -> // View's been inflated or state read in this block has been updated // Add logic here if necessary // As selectedItem is read here, AndroidView will recompose // whenever the state changes // Example of Compose -> View communication view.selectedItem = selectedItem } ) } @Composable fun ContentExample() { Column(Modifier.fillMaxSize()) { Text("Look at this CustomView!") CustomView() } }
ビュー バインディングを使用した AndroidView
XML レイアウトを埋め込むには、androidx.compose.ui:ui-viewbinding
ライブラリで提供される AndroidViewBinding
API を使用します。そのためには、プロジェクトでビュー バインディングを有効にする必要があります。
@Composable fun AndroidViewBindingExample() { AndroidViewBinding(ExampleLayoutBinding::inflate) { exampleView.setBackgroundColor(Color.GRAY) } }
遅延リストの AndroidView
遅延リスト(LazyColumn
、LazyRow
、Pager
など)で AndroidView
を使用している場合は、バージョン 1.4.0-rc01 で導入された AndroidView
オーバーロードの使用を検討してください。このオーバーロードにより、Lazy リストの場合と同様に、包含するコンポジションが再利用されるときに、Compose は基盤となる View
インスタンスを再利用できます。
この AndroidView
のオーバーロードには、次の 2 つのパラメータが追加されています。
onReset
-View
が再利用されることを通知するために呼び出されるコールバック。ビューの再利用を有効にするには、この値を null 以外にする必要があります。onRelease
(省略可)-View
がコンポジションを終了し、再び使用されないことを通知するために呼び出されるコールバック。
@OptIn(ExperimentalComposeUiApi::class) @Composable fun AndroidViewInLazyList() { LazyColumn { items(100) { index -> AndroidView( modifier = Modifier.fillMaxSize(), // Occupy the max size in the Compose UI tree factory = { context -> MyView(context) }, update = { view -> view.selectedItem = index }, onReset = { view -> view.clear() } ) } } }
Compose 内のフラグメント
AndroidViewBinding
コンポーザブルを使用して、Fragment
を Compose に追加します。AndroidViewBinding
には、コンポーザブルがコンポジションから離れたときにフラグメントを削除するなど、フラグメント固有の処理があります。
そのためには、FragmentContainerView
を含む XML を Fragment
のホルダーとしてインフレートします。
たとえば、my_fragment_layout.xml
が定義されている場合、android:name
XML 属性を Fragment
のクラス名に置き換えて次のようなコードを使用できます。
<androidx.fragment.app.FragmentContainerView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/fragment_container_view" android:layout_width="match_parent" android:layout_height="match_parent" android:name="com.example.compose.snippets.interop.MyFragment" />
Compose で、このフラグメントを次のようにインフレートします。
@Composable fun FragmentInComposeExample() { AndroidViewBinding(MyFragmentLayoutBinding::inflate) { val myFragment = fragmentContainerView.getFragment<MyFragment>() // ... } }
同じレイアウトで複数のフラグメントを使用する必要がある場合は、FragmentContainerView
ごとに一意の ID を定義していることを確認してください。
Compose から Android フレームワークを呼び出す
Compose は、Android フレームワーク クラス内で動作します。たとえば、Activity
や Fragment
などの Android ビューのクラスでホストされているため、Context
、システム リソース、Service
、BroadcastReceiver
などの Android フレームワーク クラスを使用することがあります。
システム リソースについて詳しくは、Compose のリソースをご覧ください。
コンポジション ローカル
CompositionLocal
クラスを使用すると、コンポーズ可能な関数を通じて暗黙的にデータを渡すことができます。通常、UI ツリーの特定のノードに値が設定されます。その値は、コンポーズ可能な関数のパラメータとして CompositionLocal
を宣言しなくても、コンポーズ可能な子孫で使用できます。
CompositionLocal
は、Compose の Android フレームワーク タイプ(Context
、Configuration
または Compose コードがホストされている View
など)の値を対応する LocalContext
、LocalConfiguration
、LocalView
に伝播するために使用されます。
IDE の予測入力で検出しやすいように CompositionLocal
クラスの先頭に Local
が付いています。
CompositionLocal
の現在の値にアクセスするには、current
プロパティを使用します。たとえば、下記のコードは Toast.makeToast
メソッドに LocalContext.current
を指定してトースト メッセージを表示します。
@Composable fun ToastGreetingButton(greeting: String) { val context = LocalContext.current Button(onClick = { Toast.makeText(context, greeting, Toast.LENGTH_SHORT).show() }) { Text("Greet") } }
より詳しい例については、このドキュメントの最後にある事例紹介: BroadcastReceivers をご覧ください。
その他の操作
必要な操作のためのユーティリティが定義されていない場合は、一般的な Compose ガイドラインに従い、データは下に流れ、イベントは上に流れるようにすることをおすすめします(詳しくは Compose における考え方をご覧ください)。たとえば、このコンポーザブルは別のアクティビティを起動します。
class OtherInteractionsActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // get data from savedInstanceState setContent { MaterialTheme { ExampleComposable(data, onButtonClick = { startActivity(Intent(this, MyActivity::class.java)) }) } } } } @Composable fun ExampleComposable(data: DataExample, onButtonClick: () -> Unit) { Button(onClick = onButtonClick) { Text(data.title) } }
事例紹介: ブロードキャスト レシーバ
Compose で移行または実装する機能の現実的な例として、CompositionLocal
と副作用を紹介します。たとえば、BroadcastReceiver
はコンポーズ可能な関数から登録する必要があります。
このソリューションでは、LocalContext
(現在のコンテキストを使用するため)、rememberUpdatedState
、および DisposableEffect
の副作用を利用します。
@Composable fun SystemBroadcastReceiver( systemAction: String, onSystemEvent: (intent: Intent?) -> Unit ) { // Grab the current context in this part of the UI tree val context = LocalContext.current // Safely use the latest onSystemEvent lambda passed to the function val currentOnSystemEvent by rememberUpdatedState(onSystemEvent) // If either context or systemAction changes, unregister and register again DisposableEffect(context, systemAction) { val intentFilter = IntentFilter(systemAction) val broadcast = object : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { currentOnSystemEvent(intent) } } context.registerReceiver(broadcast, intentFilter) // When the effect leaves the Composition, remove the callback onDispose { context.unregisterReceiver(broadcast) } } } @Composable fun HomeScreen() { SystemBroadcastReceiver(Intent.ACTION_BATTERY_CHANGED) { batteryStatus -> val isCharging = /* Get from batteryStatus ... */ true /* Do something if the device is charging */ } /* Rest of the HomeScreen */ }
次のステップ
ビューで Compose を使用する際と Compose でビューを使用する際の相互運用 API について説明したので、その他の考慮事項についてさらに詳しく見ていきましょう。
あなたへのおすすめ
- 注: JavaScript がオフになっている場合はリンクテキストが表示されます
- その他の考慮事項
- Compose における副作用
- CompositionLocal でローカルにスコープ設定されたデータ