استفاده از Views در Compose

شما می‌توانید سلسله مراتب نمای اندروید را در یک رابط کاربری Compose بگنجانید. این رویکرد به ویژه در صورتی مفید است که بخواهید از عناصر رابط کاربری که هنوز در Compose در دسترس نیستند، مانند AdView ، استفاده کنید. این رویکرد همچنین به شما امکان می‌دهد از نماهای سفارشی که ممکن است طراحی کرده باشید، دوباره استفاده کنید.

برای اضافه کردن یک عنصر view یا سلسله مراتب، از Composable AndroidView استفاده کنید. AndroidView یک لامبدا ارسال می‌شود که یک View را برمی‌گرداند. AndroidView همچنین یک callback update ارائه می‌دهد که هنگام inflate شدن view فراخوانی می‌شود. AndroidView هر زمان که یک State خوانده شده در callback تغییر کند، دوباره ترکیب می‌شود. AndroidView ، مانند بسیاری از composableهای داخلی دیگر، یک پارامتر Modifier می‌گیرد که می‌توان از آن، به عنوان مثال، برای تنظیم موقعیت آن در composable والد استفاده کرد.

@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، از API AndroidViewBinding استفاده کنید که توسط کتابخانه androidx.compose.ui:ui-viewbinding ارائه می‌شود. برای انجام این کار، پروژه شما باید view binding را فعال کند.

@Composable
fun AndroidViewBindingExample() {
    AndroidViewBinding(ExampleLayoutBinding::inflate) {
        exampleView.setBackgroundColor(Color.GRAY)
    }
}

AndroidView در لیست‌های تنبل

اگر از یک AndroidView در یک لیست Lazy ( LazyColumn ، LazyRow ، Pager و غیره) استفاده می‌کنید، استفاده از AndroidView overload معرفی شده در نسخه 1.4.0-rc01 را در نظر بگیرید. این overload به Compose اجازه می‌دهد تا هنگام استفاده مجدد از ترکیب حاوی، از نمونه View اصلی استفاده مجدد کند، همانطور که در مورد لیست‌های Lazy نیز صادق است.

این بارگذاری بیش از حد AndroidView دو پارامتر اضافی اضافه می‌کند:

  • onReset - یک فراخوانی برگشتی که برای اعلام آمادگی برای استفاده مجدد از View فراخوانی می‌شود. برای فعال کردن قابلیت استفاده مجدد از View، این مقدار باید غیر تهی (non-null) باشد.
  • 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()
                }
            )
        }
    }
}

قطعات در نوشتن

از AndroidFragment composable برای اضافه کردن یک Fragment در Compose استفاده کنید. AndroidFragment قابلیت مدیریت مختص به Fragment را دارد، مثلاً می‌تواند Fragment را وقتی که Composable از کامپوزیشن خارج می‌شود، حذف کند.

برای اضافه کردن یک fragment، از AndroidFragment composable استفاده کنید. شما یک کلاس Fragment را به AndroidFragment ارسال می‌کنید، که سپس یک نمونه از آن کلاس را مستقیماً به composition اضافه می‌کند. AndroidFragment همچنین یک شیء fragmentState برای ایجاد AndroidFragment با یک حالت مشخص، arguments برای ارسال به fragment جدید و یک فراخوانی onUpdate که fragment را از composition ارائه می‌دهد، فراهم می‌کند. مانند بسیاری از composableهای داخلی دیگر، AndroidFragment یک پارامتر Modifier می‌پذیرد که می‌توانید از آن، به عنوان مثال، برای تنظیم موقعیت آن در composable والد استفاده کنید.

AndroidFragment در Compose به صورت زیر فراخوانی کنید:

@Composable
fun FragmentInComposeExample() {
    AndroidFragment<MyFragment>()
}

فراخوانی چارچوب اندروید از Compose

Compose درون کلاس‌های فریم‌ورک اندروید عمل می‌کند. برای مثال، روی کلاس‌های View اندروید مانند Activity یا Fragment میزبانی می‌شود و ممکن است از کلاس‌های فریم‌ورک اندروید مانند Context ، system resources، Service یا BroadcastReceiver استفاده کند.

برای کسب اطلاعات بیشتر در مورد منابع سیستم، به منابع در Compose مراجعه کنید.

ترکیب‌بندی افراد محلی

کلاس‌های CompositionLocal امکان ارسال داده‌ها را به صورت ضمنی از طریق توابع composable فراهم می‌کنند. آن‌ها معمولاً مقداری در یک گره خاص از درخت رابط کاربری دارند. آن مقدار می‌تواند توسط فرزندان composable آن بدون اعلام CompositionLocal به عنوان پارامتر در تابع composable مورد استفاده قرار گیرد.

CompositionLocal برای انتشار مقادیر برای انواع چارچوب اندروید در Compose مانند Context ، Configuration یا View که کد Compose در آن با LocalContext ، LocalConfiguration یا LocalView مربوطه میزبانی می‌شود، استفاده می‌شود. توجه داشته باشید که کلاس‌های CompositionLocal برای قابلیت کشف بهتر با تکمیل خودکار در IDE، با Local پیشوند می‌شوند.

با استفاده از ویژگی current یک CompositionLocal به مقدار current آن دسترسی پیدا کنید. برای مثال، کد زیر با ارائه LocalContext.current در متد Toast.makeToast یک پیام toast را نشان می‌دهد.

@Composable
fun ToastGreetingButton(greeting: String) {
    val context = LocalContext.current
    Button(onClick = {
        Toast.makeText(context, greeting, Toast.LENGTH_SHORT).show()
    }) {
        Text("Greet")
    }
}

برای مثال کامل‌تر، به بخش «مطالعه موردی: گیرنده‌های پخش» در انتهای این سند نگاهی بیندازید.

سایر تعاملات

اگر برای تعاملی که نیاز دارید، ابزاری تعریف نشده باشد، بهترین روش پیروی از دستورالعمل کلی Compose است، داده‌ها به سمت پایین جریان می‌یابند، رویدادها به سمت بالا جریان می‌یابند (که در بخش «تفکر در Compose » به تفصیل مورد بحث قرار گرفته است). برای مثال، این composable یک فعالیت متفاوت را راه‌اندازی می‌کند:

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 باید از یک تابع composable ثبت شود.

این راهکار از 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های قابلیت همکاری هنگام استفاده از Compose در Views و برعکس آشنا شدید، برای کسب اطلاعات بیشتر، صفحه ملاحظات دیگر را بررسی کنید.

{% کلمه به کلمه %} {% فعل کمکی %} {% کلمه به کلمه %} {% فعل کمکی %}