میتوانید سلسلهمراتب «نمای Android» را در «رابط کاربری Compose» اضافه کنید. این رویکرد بهویژه زمانی مفید است که میخواهید از عناصر میانای کاربری استفاده کنید که هنوز در Compose دردسترس نیستند، مانند AdView.
این رویکرد همچنین به شما امکان میدهد از نماهای سفارشی که ممکن است طراحی کرده باشید دوباره استفاده کنید.
برای گنجاندن عنصر یا سلسلهمراتب نما، از ترکیبپذیر AndroidView
استفاده کنید. AndroidView یک LAMBDA را رد میکند که
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
API که توسط کتابخانه androidx.compose.ui:ui-viewbinding ارائه شده است استفاده کنید. برای
انجام این کار، پروژه شما باید اتصال نما را فعال کند.
@Composable fun AndroidViewBindingExample() { AndroidViewBinding(ExampleLayoutBinding::inflate) { exampleView.setBackgroundColor(Color.GRAY) } }
AndroidView در فهرستهای Lazy
اگر از AndroidView در فهرست Lazy (LazyColumn، LazyRow،
Pager، و غیره) استفاده میکنید، استفاده از سربارگذاری
AndroidView معرفیشده در نسخه 1.4.0-rc01 را
مدنظر قرار دهید. این اضافهبار به Compose اجازه میدهد تا نمونه View زیربنایی را زمانی که ترکیببندی حاوی آن مجدداً استفاده میشود، دوباره استفاده کند، مانند مورد فهرستهای Lazy.
این اضافهبار 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 دارای مدیریت خاص قطعه است، مانند برداشتن قطعه وقتیکه ترکیبشدنی ترکیب را ترک میکند.
برای گنجاندن قطعه، از
AndroidFragment composable استفاده کنید. کلاس Fragment را به AndroidFragment ارسال میکنید، که سپس
نمونهای از آن کلاس را مستقیماً به ترکیببندی اضافه میکند. AndroidFragment همچنین
یک شیء fragmentState برای ایجاد AndroidFragment با یک
وضعیت مشخص، arguments برای ارسال به قطعه جدید، و یک callback onUpdate
که قطعه را از ترکیببندی ارائه میدهد، فراهم میکند. مانند بسیاری از
ترکیبشدنیهای داخلی دیگر، AndroidFragment پارامتر Modifier را میپذیرد
که میتوانید از آن، برای مثال،
برای تنظیم موقعیت آن در ترکیبشدنی والد استفاده کنید.
AndroidFragment را در Compose بهصورت زیر فراخوانی کنید:
@Composable fun FragmentInComposeExample() { AndroidFragment<MyFragment>() }
وضعیت چرخه حیات Cap Fragment
در 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 است تا
با تکمیل خودکار در IDE بهتر قابلکشف باشند.
بااستفاده از ویژگی current، به مقدار فعلی CompositionLocal دسترسی پیدا کنید. برای مثال، کد زیر با ارائه
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) } }