يمكنك تضمين هيكلية طرق عرض Android في واجهة مستخدم 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 (خطوة انتقالية)
استخدِم الدالة المركّبة AndroidFragment لإضافة Fragment في Compose.
تتضمّن AndroidFragment معالجة خاصة بالـ Fragment، مثل إزالة الـ Fragment عندما تغادر الدالة المركّبة التكوين.
لتضمين جزء، استخدِم الدالة المركّبة AndroidFragment. يمكنك تمرير فئة Fragment إلى AndroidFragment، التي تضيف بعد ذلك مثيلاً من هذه الفئة مباشرةً إلى التركيب. توفّر السمة AndroidFragment أيضًا عنصر fragmentState لإنشاء AndroidFragment بحالة معيّنة، وarguments لتمريرها إلى الجزء الجديد، وonUpdate ردّ اتصال يوفّر الجزء من التركيب. مثل العديد من العناصر القابلة للإنشاء المضمّنة الأخرى، تقبل الدالة AndroidFragment المَعلمة Modifier التي يمكنك استخدامها، على سبيل المثال، لضبط موضعها في العنصر القابل للإنشاء الرئيسي.
استدعِ الدالة AndroidFragment في Compose على النحو التالي:
@Composable fun FragmentInComposeExample() { AndroidFragment<MyFragment>() }
حالة مراحل نشاط Cap Fragment
في الإصدار 1.9.0 من Fragment والإصدارات الأحدث، يمكنك استخدام المَعلمة maxLifecycle للحدّ من حالة دورة حياة Fragment المضمّنة.
على سبيل المثال، في HorizontalPager، يمكنك ضبط maxLifecycle بشكل ديناميكي على RESUMED فقط عندما تكون الصفحة المقابلة نشطة، مع إبقاء عدد الصفحات غير الظاهرة على الشاشة عند STARTED. عندما ينتقل المستخدم إلى صفحة أخرى، يصبح الحدّ الأقصى لعدد الأجزاء في الصفحة السابقة STARTED. يؤدي ذلك إلى إيقاف أو إلغاء أحمال العمل
المحدّدة النطاق بـ RESUMED (مثل الروتينات الفرعية التي يتم تشغيلها في
repeatOnLifecycle(RESUMED))، ما يمنع الصفحات غير الظاهرة على الشاشة من تنفيذ
عمليات لا يمكن تنفيذها إلا في المقدّمة، مع إبقاء واجهة المستخدم الخاصة بها مهيأة عند STARTED:
HorizontalPager(state = pagerState) { page -> // Dynamically cap the lifecycle state based on whether the page is selected val maxLifecycle = if (pagerState.settledPage == page) { Lifecycle.State.RESUMED } else { Lifecycle.State.STARTED } when (page) { 0 -> AndroidFragment<HomeFragment>(maxLifecycle = maxLifecycle) 1 -> AndroidFragment<LibraryFragment>(maxLifecycle = maxLifecycle) /* Other pages and corresponding fragments */ } }
استدعاء إطار عمل 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") } }
مستقبِلات البث
لعرض 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 العامة، أي تنتقل البيانات إلى الأسفل، وتنتقل الأحداث إلى الأعلى (تمت مناقشة ذلك بالتفصيل في التفكير في 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) } }