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 funkcji kompozycyjnej AndroidView
. AndroidView
otrzymuje wyrażenie lambda zwracające wartość View
. Funkcja AndroidView
udostępnia również wywołanie zwrotne update
, które jest wywoływane, gdy widok danych jest zawyżony. AndroidView
jest ponownie tworzony, gdy State
odczytany w wywołaniu zwrotnym ulegnie zmianie. AndroidView
, podobnie jak wiele innych wbudowanych funkcji kompozycyjnych, wykorzystuje parametr Modifier
, którego można użyć np. do ustawienia pozycji w nadrzędnej funkcji kompozycyjnej.
@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 umieścić układ XML, użyj interfejsu API AndroidViewBinding
dostępnego w bibliotece androidx.compose.ui:ui-viewbinding
. Aby to zrobić, musisz włączyć wiązanie widoku w projekcie.
@Composable fun AndroidViewBindingExample() { AndroidViewBinding(ExampleLayoutBinding::inflate) { exampleView.setBackgroundColor(Color.GRAY) } }
AndroidView
na listach leniwych
Jeśli używasz parametru AndroidView
na liście leniwej (LazyColumn
, LazyRow
, Pager
itp.), rozważ zastosowanie przeciążenia AndroidView
wprowadzonego 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.
To przeciążenie tymi parametrami (AndroidView
) dodaje 2 dodatkowe parametry:
onReset
– wywołanie zwrotne wywoływane, aby zasygnalizować, żeView
ma zostać użyty ponownie. Aby można było ponownie użyć widoku danych, wartość nie może być pusta.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, upewnij się, że dla każdego z nich masz zdefiniowany 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 systemowych znajdziesz w artykule Zasoby w 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ładanej bez deklarowania CompositionLocal
jako parametru w funkcji składanej.
Funkcja CompositionLocal
służy do rozpowszechniania wartości dla typów platform Androida w tworzeniu, takich jak Context
, Configuration
lub View
, w których kod tworzenia wiadomości jest hostowany z odpowiednim identyfikatorem LocalContext
, LocalConfiguration
lub LocalView
.
Pamiętaj, że klasy CompositionLocal
są poprzedzone ciągiem Local
, aby ułatwić ich wykrywanie przez funkcję autouzupełniania w IDE.
Aby uzyskać dostęp do bieżącej wartości elementu CompositionLocal
, użyj jego właściwości current
. Na przykład poniższy kod wyświetla toast za pomocą parametru LocalContext.current
w metodzie Toast.makeToast
.
@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 określonego narzędzia odpowiadającego potrzebnej interakcji, sprawdzoną metodą jest przestrzeganie ogólnych wskazówek dotyczących tworzenia wiadomości: dane przepływają w dół, a zdarzenia zmieniają się w górę (szczegóły znajdziesz bardziej szczegółowo w artykule Thinking in Compose). Na przykład ten program kompozycyjny uruchamia inne działanie:
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 zostać zarejestrowana z funkcji składanej.
Rozwiązanie używa LocalContext
do wykorzystania bieżącego kontekstu oraz 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 funkcji Utwórz w widokach danych i odwrotnie. Więcej informacji znajdziesz na stronie Inne uwagi.
Polecane dla Ciebie
- Uwaga: tekst linku wyświetla się, gdy JavaScript jest wyłączony
- Inne kwestie
- Efekty uboczne w edytorze
- Dane ograniczone do lokalizacji za pomocą CompositionLocal