W interfejsie tworzenia możesz uwzględnić hierarchię widoku Androida. To podejście jest szczególnie przydatne, jeśli chcesz używać elementów interfejsu użytkownika, które nie są jeszcze dostępne w Compose, takich jak AdView
.
Dzięki temu możesz też ponownie używać utworzonych wcześniej widoków niestandardowych.
Aby uwzględnić element widoku lub hierarchię, użyj kompozytu AndroidView
. AndroidView
otrzymuje wyrażenie lambda zwracające wartość View
. AndroidView
udostępnia też funkcję update
, która jest wywoływana, gdy widok jest napełniany. AndroidView
jest ponownie tworzony, gdy State
odczytany w wywołaniu zwrotnym ulegnie zmianie. AndroidView
, podobnie jak wiele innych wbudowanych komponentów, przyjmuje parametr Modifier
, który można wykorzystać na przykład do ustawienia jego pozycji w komponencie nadrzędnym.
@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
z powiązaniem widoku
Aby osadzić układ XML, użyj interfejsu AndroidViewBinding
, który jest udostępniany przez bibliotekę androidx.compose.ui:ui-viewbinding
. Aby to zrobić, musisz włączyć w projekcie wiązanie widoku.
@Composable fun AndroidViewBindingExample() { AndroidViewBinding(ExampleLayoutBinding::inflate) { exampleView.setBackgroundColor(Color.GRAY) } }
AndroidView
na listach leniwych
Jeśli używasz elementu AndroidView
na liście Lazy (LazyColumn
, LazyRow
, Pager
itp.), rozważ użycie przeciążenia AndroidView
, które zostało wprowadzone w wersji 1.4.0-rc01. Ta przeciążenie pozwala Compose używać ponownie instancji View
, gdy kompozycja zawierająca jest używana ponownie w takim samym stanie, jak w przypadku list leniwych.
Ta przeciążona wersja funkcji AndroidView
zawiera 2 dodatkowe parametry:
onReset
– wywołanie zwrotne wywoływane, aby zasygnalizować, żeView
ma zostać użyty ponownie. Aby umożliwić ponowne użycie widoku, wartość tego pola nie może być równa null.onRelease
(opcjonalnie) – wywołanie zwrotne wywoływane, aby zasygnalizować, żeView
opuścił kompozycję i nie będzie już używany ponownie.
@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() } ) } } }
Fragmenty w edytorze
Aby dodać Fragment
w sekcji Redagowanie, użyj komponentu AndroidViewBinding
.
AndroidViewBinding
obsługuje fragmenty na różne sposoby, np. usuwa fragment, gdy kompozybilny element opuszcza kompozycję.
Aby to zrobić, wczytaj plik XML zawierający element FragmentContainerView
, który będzie stanowił element 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" />
W edytorze tekstu rozwiń ten fragment 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, pamiętaj, aby dla każdego z nich zdefiniować unikalny identyfikator.FragmentContainerView
Wywoływanie platformy Android z Compose
Compose działa w ramach klas frameworka Androida. Na przykład jest ona hostowana na klasach widoku Androida, takich jak Activity
lub Fragment
, i może używać klas frameworka Androida, takich jak Context
, zasoby systemowe, Service
lub BroadcastReceiver
.
Więcej informacji o zasobach systemu znajdziesz w artykule Zasoby w usłudze Compose.
Kompozycja Lokalna
CompositionLocal
klasy umożliwiają przekazywanie danych w drugim planie za pomocą funkcji składanych. Zwykle są one dostarczane z wartością w określonym węźle drzewa interfejsu. Ta wartość może być używana przez potomków funkcji składanych bez deklarowania CompositionLocal
jako parametru w funkcji składanej.
CompositionLocal
służy do propagowania wartości typów platformy Android w Compose, takich jak Context
, Configuration
lub View
, w których hostowany jest kod Compose z odpowiednim LocalContext
, LocalConfiguration
lub LocalView
.
Pamiętaj, że klasy CompositionLocal
mają prefiks Local
, aby ułatwić ich znajdowanie za pomocą autouzupełniania w IDE.
Uzyskaj dostęp do bieżącej wartości elementu CompositionLocal
, korzystając z właściwości current
. Na przykład kod poniżej wyświetla komunikat toast, przekazując do metody Toast.makeToast
wartość LocalContext.current
.
@Composable fun ToastGreetingButton(greeting: String) { val context = LocalContext.current Button(onClick = { Toast.makeText(context, greeting, Toast.LENGTH_SHORT).show() }) { Text("Greet") } }
Pełniejszy przykład znajdziesz w sekcji Studium przypadku: BroadcastReceivers na końcu tego dokumentu.
Inne interakcje
Jeśli nie ma narzędzia do interakcji, których potrzebujesz, najlepiej postępować zgodnie z ogólnymi wytycznymi dotyczącymi tworzenia wiadomości: dane przepływają w dół, zdarzenia w górę (więcej informacji znajdziesz w artykule Myślenie o komponowaniu wiadomości). Na przykład ta kompozycja 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 sygnału radiowego
Aby pokazać bardziej realistyczny przykład funkcji, które warto przenieść lub zaimplementować w Compose, oraz zaprezentować CompositionLocal
i efekty uboczne, załóżmy, że BroadcastReceiver
musi być zarejestrowana z funkcji składanej.
Rozwiązanie korzysta z elementu LocalContext
, aby wykorzystać bieżący kontekst, oraz z elementów rememberUpdatedState
i DisposableEffect
, aby uwzględnić skutki uboczne.
@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
Teraz, gdy znasz interfejsy API interoperacyjności podczas korzystania z Compose in Views i odwrotnie, zapoznaj się ze stroną Inne kwestie, aby dowiedzieć się więcej.
Polecane dla Ciebie
- Uwaga: tekst linku jest wyświetlany, gdy obsługa JavaScript jest wyłączona
- Inne kwestie
- Efekty uboczne w edytorze
- Dane ograniczone do lokalizacji za pomocą CompositionLocal