אפשר לכלול היררכיית View של Android בממשק המשתמש של Compose. הגישה הזו שימושית במיוחד אם רוצים להשתמש ברכיבי ממשק משתמש שעדיין לא זמינים ב-Compose, כמו AdView
.
הגישה הזו גם מאפשרת לכם לעשות שימוש חוזר בתצוגות בהתאמה אישית שעיצבתם.
כדי לכלול רכיב תצוגה או היררכיה, צריך להשתמש בתוכן הקומפוזבילי AndroidView
. ל-AndroidView
מועברת פונקציית lambda שמחזירה View
. AndroidView
מספק גם פונקציית קריאה חוזרת (callback) מסוג update
שנקראת כשהתצוגה מורחבת. ה-AndroidView
יתבצע מחדש בכל פעם שקריאת ה-State
בתוך קריאת החזרה (callback) תשתנה. 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, משתמשים ב-API AndroidViewBinding
שמסופק על ידי הספרייה androidx.compose.ui:ui-viewbinding
. כדי לעשות זאת, צריך להפעיל בפרויקט את קישור התצוגה המפורטת.
@Composable fun AndroidViewBindingExample() { AndroidViewBinding(ExampleLayoutBinding::inflate) { exampleView.setBackgroundColor(Color.GRAY) } }
AndroidView
ברשימות 'לאט'
אם אתם משתמשים ב-AndroidView
ברשימה 'עצמה' (LazyColumn
, LazyRow
, Pager
וכו'), כדאי להשתמש בעומס היתר של AndroidView
שהושק בגרסה 1.4.0-rc01. עומס יתר זה מאפשר ל-Compose לעשות שימוש חוזר במכונה הבסיסית של View
כשנעשה שימוש חוזר בהרכבה המכילה, כמו במקרה של רשימות 'לא עצלניות'.
לעומס יתר הזה של AndroidView
יש עוד 2 פרמטרים:
onReset
– קריאה חוזרת (callback) שמפעילים כדי לסמן שה-View
עומד לשימוש חוזר. כדי לאפשר שימוש חוזר בתצוגה, הערך הזה לא יכול להיות null.onRelease
(אופציונלי) – בוצעה קריאה חוזרת (callback) כדי לסמן שה-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
משתמשים ב-composable AndroidViewBinding
כדי להוסיף Fragment
ב-Compose.
ל-AndroidViewBinding
יש טיפול ספציפי למקטעים, כמו הסרת המקטע כשהתוכן הקומפוזבילי משאיר את הקומפוזביליות.
כדי לעשות זאת, צריך לנפח קובץ XML שמכיל FragmentContainerView
בתור המאגר של Fragment
.
לדוגמה, אם הגדרתם את my_fragment_layout.xml
, תוכלו להשתמש בקוד כזה ולהחליף את מאפיין ה-XML android:name
בשם הכיתה של 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
.
שליחת קריאה ל-framework של Android מהכתיבה
Compose פועל בתוך הכיתות של מסגרת Android. לדוגמה, הוא מתארח במחלקות של Android View, כמו Activity
או Fragment
, ועשוי להשתמש במחלקות framework של Android כמו Context
, משאבי מערכת, Service
או BroadcastReceiver
.
מידע נוסף על משאבי המערכת זמין במאמר משאבים ב-Compose.
רכיבים מקומיים של יצירה מוזיקלית
מחלקות CompositionLocal
מאפשרות להעביר נתונים באופן מרומז באמצעות פונקציות קומפוזביליות. בדרך כלל מציינים להם ערך בצומת מסוים בעץ של ממשק המשתמש. הצאצאים הקומפוזביליים שלו יכולים להשתמש בערך הזה בלי להצהיר על CompositionLocal
כפרמטר בפונקציה הקומפוזבילית.
CompositionLocal
משמש להפצת ערכים של סוגי מסגרות של Android ב-Compose, כמו Context
, Configuration
או View
שבו מתארח קוד Compose עם LocalContext
, LocalConfiguration
או LocalView
התואם.
הערה: לכיתות CompositionLocal
מצורף הקידומת Local
כדי לשפר את הגילוי שלהן באמצעות ההשלמה האוטומטית בסביבת הפיתוח המשולבת (IDE).
גישה לערך הנוכחי של CompositionLocal
באמצעות המאפיין current
. לדוגמה, הקוד הבא מציג הודעת טוסטים על ידי העברת הערך LocalContext.current
לשיטה Toast.makeToast
.
@Composable fun ToastGreetingButton(greeting: String) { val context = LocalContext.current Button(onClick = { Toast.makeText(context, greeting, Toast.LENGTH_SHORT).show() }) { Text("Greet") } }
לדוגמה מלאה יותר, אפשר לעיין בקטע Case Study: 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 */ }
השלבים הבאים
עכשיו, אחרי שסיפרנו לכם על ממשקי ה-API לתאימות הדדית כשמשתמשים ב-Compose ב-Views ולהפך, כדאי לעיין בדף שיקולים נוספים כדי לקבל מידע נוסף.
מומלץ עבורך
- הערה: טקסט הקישור מוצג כאשר JavaScript מושבת
- שיקולים נוספים
- תופעות לוואי ב-Compose
- נתונים ברמת המיקום המקומי באמצעות CompositionLocal