אפשר לכלול היררכיית View של Android בממשק המשתמש של Compose. הגישה הזו שימושית במיוחד אם רוצים להשתמש ברכיבי ממשק משתמש שעדיין לא זמינים ב-Compose, כמו AdView
.
הגישה הזו מאפשרת גם לעשות שימוש חוזר בתצוגות בהתאמה אישית שיצרתם.
כדי לכלול רכיב תצוגה או היררכיה, משתמשים ב-composable 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
כשנעשה שימוש חוזר בהרכבה המכילה, כמו במקרה של רשימות Lazy.
עומס יתר זה של 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
.
קריאה למסגרת Android מ-Compose
Compose פועל בתוך הכיתות של מסגרת Android. לדוגמה, הוא מתארח בכיתות View של Android, כמו Activity
או Fragment
, ויכול להשתמש בכיתות של מסגרת 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