Ansichten in „Compose“ verwenden

Sie können eine Android View-Hierarchie in eine Compose-UI einbinden. Dieser Ansatz ist besonders nützlich, wenn Sie UI-Elemente verwenden möchten, die in Schreiben, Gefällt mir AdView Auf diese Weise können Sie auch benutzerdefinierte Ansichten wiederverwenden, die Sie erstellt haben.

Um ein Ansichtselement oder eine Hierarchie hinzuzufügen, verwenden Sie die AndroidView zusammensetzbar. AndroidView wird eine Lambda-Funktion übergeben, die ein View AndroidView bietet auch eine update -Callback, der aufgerufen wird, wenn sich die Ansicht erhöht. AndroidView wird neu zusammengesetzt. wenn sich ein State-Lesevorgang innerhalb des Callbacks ändert. AndroidView, wie viele anderen integrierten zusammensetzbaren Funktionen, verwendet einen Modifier-Parameter, der verwendet werden kann, um seine Position in der übergeordneten zusammensetzbaren Funktion festzulegen.

@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 mit Bindung der Ansicht

Verwenden Sie zum Einbetten eines XML-Layouts die Methode AndroidViewBinding API, die von der androidx.compose.ui:ui-viewbinding-Bibliothek bereitgestellt wird. Bis Wenn Sie dies tun möchten, muss in Ihrem Projekt die Bindung zum Ansehen aktiviert sein.

@Composable
fun AndroidViewBindingExample() {
    AndroidViewBinding(ExampleLayoutBinding::inflate) {
        exampleView.setBackgroundColor(Color.GRAY)
    }
}

AndroidView in Lazy-Listen

Wenn Sie ein AndroidView in einer Lazy-Liste verwenden (LazyColumn, LazyRow, Pager usw.), sollten Sie die Verwendung von AndroidView in Betracht ziehen. in Version 1.4.0-rc01 eingeführt. Aufgrund dieser Überlastung kann Compose Die zugrunde liegende View-Instanz, wenn die enthaltende Zusammensetzung unverändert wiederverwendet wird was bei Lazy Listen der Fall ist.

Diese Überlastung von AndroidView fügt zwei zusätzliche Parameter hinzu:

  • onReset – ein Callback, der ausgelöst wird, um zu signalisieren, dass das View gleich beginnt. wiederverwendet werden. Der Wert darf nicht null sein, damit Ansichten wiederverwendet werden können.
  • onRelease (optional): Ein Callback, der aufgerufen wird, um zu signalisieren, dass das View hat die Zusammensetzung verlassen und wird nicht erneut verwendet.

@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()
                }
            )
        }
    }
}

Fragmente in Compose

Mit der zusammensetzbaren Funktion AndroidViewBinding können Sie in „Schreiben“ ein Fragment einfügen. Bei AndroidViewBinding erfolgt eine fragmentierte Verarbeitung, wie z. B. das Entfernen des Fragment zurück, wenn die zusammensetzbare Funktion die Komposition verlässt.

Dazu bläst du eine XML-Datei auf, die FragmentContainerView enthält. als Inhaber von Fragment.

Wenn Sie beispielsweise my_fragment_layout.xml definiert haben, können Sie Folgendes verwenden: Code wie diesen aussehen und dabei das XML-Attribut android:name durch Ihre Klassenname von 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" />

Blenden Sie dieses Fragment in Compose wie folgt auf:

@Composable
fun FragmentInComposeExample() {
    AndroidViewBinding(MyFragmentLayoutBinding::inflate) {
        val myFragment = fragmentContainerView.getFragment<MyFragment>()
        // ...
    }
}

Wenn Sie mehrere Fragmente im selben Layout verwenden müssen, eindeutige ID für jede FragmentContainerView definiert.

Android-Framework aus Compose aufrufen

Compose wird in den Android-Framework-Klassen ausgeführt. Zum Beispiel werden sie auf Android View-Klassen wie Activity oder Fragment und verwenden möglicherweise Android Framework-Klassen wie Context, Systemressourcen, Service oder BroadcastReceiver.

Weitere Informationen zu Systemressourcen finden Sie unter Ressourcen in Compose.

Zusammensetzung von Ortsansässigen

CompositionLocal -Klassen ermöglichen die implizite Weitergabe von Daten über zusammensetzbare Funktionen. Sie sind in der Regel mit einem Wert in einem bestimmten Knoten des UI-Baums bereitgestellt. Dieser Wert kann von seinen zusammensetzbaren Nachfolgern verwendet werden, ohne das CompositionLocal-Element zu deklarieren als Parameter in der zusammensetzbaren Funktion verwenden.

Mit CompositionLocal werden Werte für Android-Framework-Typen weitergegeben in Verfassen, z. B. Context, Configuration oder die View, in der das Feld „Schreiben“ mit der entsprechenden URL gehostet wird, LocalContext, LocalConfiguration oder LocalView. Beachten Sie, dass CompositionLocal-Klassen zur besseren Verbesserung das Präfix Local vorangestellt ist. mit der automatischen Vervollständigung in der IDE.

Greifen Sie über dessen current auf den aktuellen Wert eines CompositionLocal zu. Property. Der folgende Code zeigt beispielsweise eine Toast-Nachricht an, indem LocalContext.current in die Toast.makeToast-Methode ein.

@Composable
fun ToastGreetingButton(greeting: String) {
    val context = LocalContext.current
    Button(onClick = {
        Toast.makeText(context, greeting, Toast.LENGTH_SHORT).show()
    }) {
        Text("Greet")
    }
}

Ein vollständigeres Beispiel finden Sie in der Fallstudie: BroadcastReceivers am Ende dieses Dokument.

Andere Interaktionen

Wenn für die gewünschte Interaktion kein Dienstprogramm definiert ist, sich an die allgemeinen Richtlinien für das Schreiben, Daten fließen nach unten, Ereignisse fließen nach oben (ausführlicher im Modul Denken in „Schreiben“). Diese zusammensetzbare Funktion startet eine andere Aktivität:

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)
    }
}

Fallstudie: Rundfunkempfänger

Ein realistischeres Beispiel für Funktionen, die Sie migrieren oder implementieren möchten in „Schreiben“ aktiviert, und um CompositionLocal und Effekte, nehmen wir an, BroadcastReceiver muss registriert werden über eine zusammensetzbare Funktion.

Die Lösung nutzt LocalContext, um den aktuellen Kontext zu verwenden, und Nebenwirkungen von rememberUpdatedState und 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 */
}

Nächste Schritte

Jetzt kennen Sie die APIs für die Interoperabilität bei der Verwendung der Funktion „Schreiben“ in Views und umgekehrt. finden Sie auf der Seite Weitere Überlegungen.