בממשק המשתמש של הכתיבה אפשר לכלול היררכיית תצוגה של Android. בגישה הזאת
שימושי במיוחד אם רוצים להשתמש ברכיבים של ממשק המשתמש שעדיין לא זמינים
כתיבה, לייק
AdView
הגישה הזו גם מאפשרת לכם לעשות שימוש חוזר בתצוגות בהתאמה אישית שעיצבתם.
כדי לכלול רכיב תצוגה או היררכיה, צריך להשתמש בAndroidView
קומפוזבילי. הפונקציה AndroidView
מועברת lambda שמחזירה
View
. AndroidView
מספק גם update
קריאה חוזרת (callback) שנשלחת כאשר התצוגה מנופחת. היצירה מחדש של AndroidView
בכל פעם שקריאה של State
במסגרת הקריאה החוזרת משתנה. 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 צריך להשתמש
AndroidViewBinding
API, שסופק על ידי הספרייה androidx.compose.ui:ui-viewbinding
. שפת תרגום
לעשות זאת, הפרויקט צריך להפעיל קישור תצוגה (view Link).
@Composable fun AndroidViewBindingExample() { AndroidViewBinding(ExampleLayoutBinding::inflate) { exampleView.setBackgroundColor(Color.GRAY) } }
AndroidView
ברשימות של עצלנים
אם משתמשים ב-AndroidView
ברשימת 'עצלים' (LazyColumn
, LazyRow
,
Pager
וכו'), כדאי להשתמש ברכיב AndroidView
עומס יתר שהוצג בגרסה 1.4.0-rc01. עומס היתר הזה מאפשר שימוש חוזר ב'כתיבה'
במכונה הבסיסית View
כשעושים שימוש חוזר ביצירה שמכילה אותה כפי שהיא
במקרה של 'רשימות של עצלנים'.
לעומס יתר הזה של AndroidView
יש עוד 2 פרמטרים:
onReset
- בוצעה קריאה חוזרת (callback) כדי לאותת שה-View
עומד להתחיל שנעשה בו שימוש חוזר. הערך חייב להיות אפס כדי לאפשר שימוש חוזר בתצוגה מפורטת.onRelease
(אופציונלי) – בוצעה קריאה חוזרת כדי לסמן שה-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() } ) } } }
מקטעים ב'פיתוח'
צריך להשתמש בתוכן הקומפוזבילי AndroidViewBinding
כדי להוסיף Fragment
לכתיבה.
ב-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 מהכתיבה
הכתיבה פועלת במחלקות של מסגרת Android. לדוגמה, הוא מתארח
ב-Android View, כמו Activity
או Fragment
, ועשויה להשתמש ב-Android
סוגי framework כמו Context
, משאבי מערכת
Service
או BroadcastReceiver
.
למידע נוסף על משאבי המערכת, ראו משאבים בכתיבה.
תושבי היצירה
CompositionLocal
סיווגים מאפשרים העברת נתונים באופן מרומז באמצעות פונקציות קומפוזביליות. אלו
בדרך כלל עם ערך בצומת מסוים של עץ ממשק המשתמש. הערך הזה יכול
לשימוש על ידי הצאצאים הקומפוזביליים שלו בלי להצהיר על CompositionLocal
בתור פרמטר בפונקציה הקומפוזבילית.
CompositionLocal
משמש להפצת ערכים לסוגי framework של Android ב-
כתיבה כמו Context
, Configuration
או View
שבה
מתארח
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") } }
כדי לקבל דוגמה מלאה יותר, אפשר לעיין במקרה לדוגמה: הקטע BroadcastReceivers בסוף מהמסמך.
אינטראקציות אחרות
אם לא הוגדר כלי עזר לאינטראקציה הדרושה, השיטה המומלצת היא לפעול בהתאם להנחיה הכללית של 'כתיבה', הנתונים זורמים למטה, האירועים זורמים למעלה (נדון בהרחבה בנושא חשיבה בחלון 'כתיבה'. לדוגמה, התוכן הקומפוזבילי מפעיל פעילות אחרת:
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) } }
מקרה לדוגמה: מקלטי שידורים
דוגמה מציאותית יותר לתכונות שכדאי להעביר או להטמיע
בחלונית הכתיבה, וכדי להציג את 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 ליכולת פעולה הדדית כשאתם משתמשים ב'כתיבה' בתצוגות אחרות' לחלופין, אפשר לעיין בדף שיקולים אחרים כדי לקבל מידע נוסף.
מומלץ עבורך
- הערה: טקסט הקישור מוצג כאשר JavaScript מושבת
- שיקולים אחרים
- תופעות לוואי ב-Compose
- נתונים בהיקף מקומי באמצעות CompositionLocal