W interfejsie Compose możesz umieścić hierarchię widoków Androida. To podejście jest szczególnie przydatne, jeśli chcesz używać elementów interfejsu, które nie są jeszcze dostępne w Compose, np. AdView
.
Dzięki temu możesz też ponownie wykorzystywać zaprojektowane przez siebie widoki niestandardowe.
Aby uwzględnić element widoku lub hierarchię, użyj funkcji kompozycyjnej AndroidView
. AndroidView
otrzymuje wyrażenie lambda, które zwraca wartość View
. AndroidView
udostępnia też update
wywołanie zwrotne, które jest wywoływane po rozwinięciu widoku. Funkcja AndroidView
jest ponownie komponowana, gdy zmieni się wartość State
odczytana w wywołaniu zwrotnym. AndroidView
, podobnie jak wiele innych wbudowanych funkcji kompozycyjnych, przyjmuje parametr Modifier
, którego można użyć np. do ustawienia jego pozycji w funkcji kompozycyjnej nadrzędnej.
@Composable fun CustomView() { var selectedItem by remember { mutableIntStateOf(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
z powiązaniem widoku
Aby osadzić układ XML, użyj interfejsu API AndroidViewBinding
, który jest udostępniany przez bibliotekę androidx.compose.ui:ui-viewbinding
. Aby to zrobić, musisz włączyć w projekcie powiązanie widoku.
@Composable fun AndroidViewBindingExample() { AndroidViewBinding(ExampleLayoutBinding::inflate) { exampleView.setBackgroundColor(Color.GRAY) } }
AndroidView
na listach leniwych
Jeśli używasz AndroidView
na liście Lazy (LazyColumn
, LazyRow
, Pager
itp.), rozważ użycie przeciążenia AndroidView
wprowadzonego w wersji 1.4.0-rc01. Ten overload umożliwia Compose ponowne użycie bazowego wystąpienia View
, gdy zawierająca kompozycja jest ponownie używana w takiej samej postaci, jak w przypadku list leniwych.
Ten przeciążony operator AndroidView
dodaje 2 dodatkowe parametry:
onReset
– wywołanie zwrotne, które sygnalizuje, że obiektView
ma zostać ponownie użyty. Aby włączyć ponowne użycie widoku, ta wartość musi być różna od null.onRelease
(opcjonalnie) – wywołanie zwrotne, które jest wywoływane, aby zasygnalizować, żeView
opuścił kompozycję i nie będzie już ponownie używany.
@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() } ) } } }
Fragmenty w Compose
Aby dodać Fragment
w Compose, użyj komponentu AndroidViewBinding
.
AndroidViewBinding
ma obsługę specyficzną dla fragmentu, np. usuwanie fragmentu, gdy funkcja kompozycyjna opuszcza kompozycję.
Aby to zrobić, rozwiń plik XML zawierający element FragmentContainerView
jako kontener dla elementu Fragment
.
Jeśli na przykład masz zdefiniowany element my_fragment_layout.xml
, możesz użyć takiego kodu, zastępując atrybut XML android:name
nazwą klasy elementu 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" />
Rozwiń ten fragment w Compose w ten sposób:
@Composable fun FragmentInComposeExample() { AndroidViewBinding(MyFragmentLayoutBinding::inflate) { val myFragment = fragmentContainerView.getFragment<MyFragment>() // ... } }
Jeśli w tym samym układzie musisz użyć kilku fragmentów, upewnij się, że każdy z nich ma unikalny identyfikator FragmentContainerView
.
Wywoływanie platformy Android z Compose
Compose działa w ramach klas platformy Android. Jest ona na przykład hostowana w klasach widoku Androida, takich jak Activity
lub Fragment
, i może korzystać z klas platformy Androida, takich jak Context
, zasoby systemowe Service
lub BroadcastReceiver
.
Więcej informacji o zasobach systemowych znajdziesz w artykule Zasoby w Compose.
Composition Locals
CompositionLocal
klasy umożliwiają niejawne przekazywanie danych za pomocą funkcji, które można łączyć. Zwykle mają one wartość w określonym węźle drzewa interfejsu. Jej wartość może być używana przez elementy kompozycyjne pochodne bez deklarowania CompositionLocal
jako parametru w funkcji kompozycyjnej.
Symbol CompositionLocal
służy do propagowania wartości typów platformy Android w Compose, takich jak Context
, Configuration
lub View
, w którym jest hostowany kod Compose, z odpowiednimi wartościami LocalContext
, LocalConfiguration
lub LocalView
.
Pamiętaj, że klasy CompositionLocal
mają przedrostek Local
, co ułatwia ich wyszukiwanie za pomocą autouzupełniania w IDE.
Aby uzyskać dostęp do bieżącej wartości CompositionLocal
, użyj właściwości current
. Na przykład poniższy kod wyświetla komunikat w formie toastu, przekazując LocalContext.current
do metody Toast.makeToast
.
@Composable fun ToastGreetingButton(greeting: String) { val context = LocalContext.current Button(onClick = { Toast.makeText(context, greeting, Toast.LENGTH_SHORT).show() }) { Text("Greet") } }
Bardziej szczegółowy przykład znajdziesz w sekcji Studium przypadku: BroadcastReceivers na końcu tego dokumentu.
Inne interakcje
Jeśli dla interakcji, której potrzebujesz, nie ma zdefiniowanego narzędzia, najlepszym rozwiązaniem jest przestrzeganie ogólnych wytycznych dotyczących Compose: dane przepływają w dół, a zdarzenia w górę (więcej informacji znajdziesz w artykule Myślenie w Compose). Na przykład ten komponent kompozycyjny uruchamia inną aktywność:
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) } }
Studium przypadku: odbiorniki
Aby przedstawić bardziej realistyczny przykład funkcji, które możesz chcieć przenieść lub zaimplementować w Compose, oraz zaprezentować CompositionLocal
i efekty uboczne, załóżmy, że z funkcji kompozycyjnej trzeba zarejestrować BroadcastReceiver
.
Rozwiązanie korzysta z funkcji LocalContext
, aby używać bieżącego kontekstu, oraz z efektów ubocznych rememberUpdatedState
i 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 */ }
Dalsze kroki
Znasz już interfejsy API interoperacyjności podczas korzystania z Compose w widokach i odwrotnie. Aby dowiedzieć się więcej, zapoznaj się ze stroną Inne kwestie.
Polecane dla Ciebie
- Uwaga: tekst linku jest wyświetlany, gdy JavaScript jest wyłączony.
- Inne kwestie, które warto wziąć pod uwagę
- Efekty uboczne w Compose
- Dane o lokalnym zakresie widoczności z użyciem funkcji CompositionLocal