يمكنك تضمين بنية Android View الهرمية في واجهة مستخدم Compose. ويكون هذا الأسلوب مفيدًا بشكل خاص إذا كنت تريد استخدام عناصر واجهة مستخدم غير متاحة بعد في Compose، مثل AdView
.
يتيح لك هذا الأسلوب أيضًا إعادة استخدام طرق العرض المخصّصة التي صمّمتها.
لتضمين عنصر عرض أو بنية هرمية، استخدِم الدالة البرمجية القابلة للإنشاء AndroidView
. يتم تمرير دالة lambda إلى AndroidView
تعرض View
. توفّر AndroidView
أيضًا update
دالة ردّ اتصال يتم استدعاؤها عند توسيع طريقة العرض. تتم إعادة إنشاء AndroidView
كلما تغيّرت قيمة State
التي تم قراءتها في الدالة التنفيذية. تتلقّى الدالة AndroidView
، مثل العديد من الدوال البرمجية الأخرى القابلة للإنشاء المضمّنة، المَعلمة Modifier
التي يمكن استخدامها، على سبيل المثال، لضبط موضعها في الدالة البرمجية القابلة للإنشاء الرئيسية.
@Composable fun CustomView() { var selectedItem by remember { mutableIntStateOf(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
التي توفّرها مكتبة androidx.compose.ui:ui-viewbinding
. لإجراء ذلك، يجب أن يفعّل مشروعك ربط العرض.
@Composable fun AndroidViewBindingExample() { AndroidViewBinding(ExampleLayoutBinding::inflate) { exampleView.setBackgroundColor(Color.GRAY) } }
AndroidView
في القوائم الكسولة
إذا كنت تستخدم AndroidView
في قائمة Lazy (LazyColumn
أو LazyRow
أو Pager
أو غير ذلك)، ننصحك باستخدام AndroidView
الذي تم تقديمه في الإصدار 1.4.0-rc01. تتيح عملية التحميل الزائد هذه لـ Compose إعادة استخدام مثيل View
الأساسي عند إعادة استخدام التركيب الحاوي كما هو، كما هو الحال مع القوائم الكسولة.
تضيف هذه الزيادة في التحميل الزائد AndroidView
مَعلمتَين إضافيتَين:
-
onReset
: دالة يتم استدعاؤها للإشارة إلى أنّView
سيتم إعادة استخدامه قريبًا. يجب أن تكون هذه القيمة غير فارغة لتفعيل إعادة استخدام العرض. -
onRelease
(اختياري): دالة ردّ يتم استدعاؤها للإشارة إلى أنّView
قد خرج من التركيب ولن تتم إعادة استخدامه مرة أخرى.
@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
استخدِم العنصر القابل للإنشاء 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. على سبيل المثال، تتم استضافته على فئات Android View، مثل Activity
أو Fragment
، وقد يستخدم فئات إطار عمل Android، مثل Context
أو موارد النظام Service
أو BroadcastReceiver
.
لمزيد من المعلومات حول موارد النظام، يمكنك الاطّلاع على الموارد في Compose.
Composition Locals
تسمح فئات CompositionLocal
بتمرير البيانات ضمنيًا من خلال الدوال القابلة للإنشاء. ويتم عادةً توفيرها بقيمة في عقدة معيّنة من شجرة واجهة المستخدم. ويمكن أن تستخدم العناصر التابعة القابلة للإنشاء هذه القيمة بدون تعريف CompositionLocal
كمعلَمة في الدالة القابلة للإنشاء.
يُستخدَم CompositionLocal
لنقل قيم أنواع إطار عمل Android في Compose، مثل Context
أو Configuration
أو View
التي يتم فيها استضافة رمز Compose مع LocalContext
أو LocalConfiguration
أو LocalView
المقابل.
يُرجى العِلم أنّ فئات CompositionLocal
يتم تحديد بادئتها بـ Local
لتسهيل العثور عليها باستخدام ميزة الإكمال التلقائي في بيئة التطوير المتكاملة.
يمكنك الوصول إلى القيمة الحالية لـ 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 في نهاية هذا المستند.
تفاعلات أخرى
إذا لم تكن هناك أداة مساعدة محدّدة للتفاعل الذي تحتاجه، فإنّ أفضل ممارسة هي اتّباع إرشادات 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 */ }
الخطوات التالية
بعد التعرّف على واجهات برمجة التطبيقات الخاصة بالتوافق عند استخدام Compose في "طرق العرض" والعكس، يمكنك الاطّلاع على صفحة اعتبارات أخرى لمعرفة المزيد.
اقتراحات مخصصة لك
- ملاحظة: يتم عرض نص الرابط عندما تكون JavaScript غير مفعّلة
- اعتبارات أخرى
- الآثار الجانبية في Compose
- البيانات ذات النطاق المحلي باستخدام CompositionLocal