استفاده از «نماها» در «نوشتن»

می‌توانید سلسله‌مراتب «نمای 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)
    }
}