میتوانید میانای کاربر مبتنی بر Compose را به برنامه موجودی که از طراحی مبتنی بر View استفاده میکند اضافه کنید.
برای ایجاد صفحهنمایش جدیدی که کاملاً مبتنی بر Compose باشد،
فعالیتتان را وادار کنید متد setContent() را فراخوانی کند و هر تابع ترکیبپذیری را که
میخواهید ارسال کند.
class ExampleActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { // In here, we can call composables! MaterialTheme { Greeting(name = "compose") } } } } @Composable fun Greeting(name: String) { Text(text = "Hello $name!") }
این کد دقیقاً شبیه چیزی است که در برنامه Compose-only پیدا میکنید.
ViewCompositionStrategy برای ComposeView
ViewCompositionStrategy
تعیین میکند که چه زمانی «ترکیببندی» باید دور انداخته شود. پیشفرض،
ViewCompositionStrategy.Default،
«ترکیببندی» را وقتی
ComposeView
زیرین از پنجره جدا میشود دور میاندازد، مگراینکه بخشی از یک محفظه ادغام مانند
RecyclerView
باشد. در برنامه تکفعالیتی فقط Compose، این رفتار پیشفرض همان چیزی است که میخواهید، اما اگر بهتدریج Compose را به پایگاه کد خود اضافه میکنید، این رفتار ممکن است در برخی سناریوها باعث ازدست رفتن وضعیت شود.
برای تغییر ViewCompositionStrategy، روش setViewCompositionStrategy() را فراخوانی کنید و استراتژی دیگری ارائه دهید.
جدول زیر سناریوهای مختلفی را که میتوانید از
ViewCompositionStrategy در آنها استفاده کنید خلاصه میکند:
ViewCompositionStrategy |
شرح و سناریو تعاملپذیری |
|---|---|
DisposeOnDetachedFromWindow |
وقتی ComposeView زیرین از پنجره جدا شود، «ترکیببندی» دور انداخته خواهد شد. از آن زمان با DisposeOnDetachedFromWindowOrReleasedFromPool جایگزین شده است.سناریو Interop: * ComposeView چه تنها عنصر در سلسلهمراتب «نما» باشد، چه در بافت صفحه ترکیبی «نما»/Compose (نه در Fragment). |
DisposeOnDetachedFromWindowOrReleasedFromPool (پیشفرض) |
مشابه DisposeOnDetachedFromWindow، وقتی «ترکیببندی» در ظرف ادغامسازی نیست، مثل RecyclerView. اگر در محفظه ادغام باشد، وقتی خود محفظه ادغام از پنجره جدا شود یا وقتی مورد دور انداخته شود (یعنی وقتی ادغام کامل باشد) دور انداخته میشود.سناریو Interop: * ComposeView چه تنها عنصر در سلسلهمراتب «نما» باشد، چه در بافت صفحه مختلط «نما»/Compose (نه در Fragment).* ComposeView بهعنوان موردی در محفظه ادغام مانند RecyclerView. |
DisposeOnLifecycleDestroyed |
وقتی Lifecycle ارائهشده ازبین برود، «ترکیببندی» دور انداخته خواهد شد.سناریو Interop * ComposeView در «نمای» Fragment. |
DisposeOnViewTreeLifecycleDestroyed |
The Composition will be disposed when the Lifecycle owned by the LifecycleOwner returned by ViewTreeLifecycleOwner.get of the next window the View is attached to is destroyed.Interop scenario: * ComposeView in a Fragment's View.* ComposeView در «نمایی» که «چرخه حیات» آن هنوز مشخص نیست. |
ComposeView در Fragments (مرحله انتقالی)
اگر میخواهید محتوای Compose UI را در یک قطعه یا چیدمان View موجود بگنجانید، از ComposeView استفاده کنید و روش setContent() آن را فراخوانی کنید. ComposeView یک View Android است.
میتوانید ComposeView را درست مثل هر View دیگری در چیدمان XML خود قرار دهید:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <androidx.compose.ui.platform.ComposeView android:id="@+id/compose_view" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
در کد منبع Kotlin، چیدمان را از منبع
چیدمان تعریفشده در XML باد کنید. سپس
ComposeView را بااستفاده از شناسه XML دریافت کنید، استراتژی «ترکیببندی» را که برای
میزبان View بهترین عملکرد را دارد تنظیم کنید، و setContent() را برای استفاده از Compose فراخوانی کنید.
class ExampleFragmentXml : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { val view = inflater.inflate(R.layout.fragment_example, container, false) val composeView = view.findViewById<ComposeView>(R.id.compose_view) composeView.apply { // Dispose of the Composition when the view's LifecycleOwner // is destroyed setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed) setContent { // In Compose world MaterialTheme { Text("Hello Compose!") } } } return view } }
یا میتوانید از اتصال نما برای دریافت ارجاع به
ComposeView با ارجاع به کلاس اتصال تولیدشده برای فایل چیدمان XML استفاده کنید:
class ExampleFragment : Fragment() { private var _binding: FragmentExampleBinding? = null // This property is only valid between onCreateView and onDestroyView. private val binding get() = _binding!! override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { _binding = FragmentExampleBinding.inflate(inflater, container, false) val view = binding.root binding.composeView.apply { // Dispose of the Composition when the view's LifecycleOwner // is destroyed setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed) setContent { // In Compose world MaterialTheme { Text("Hello Compose!") } } } return view } override fun onDestroyView() { super.onDestroyView() _binding = null } }
شکل ۱. این برونداد کدی را نشان میدهد که عناصر Compose را در سلسلهمراتب میانای کاربری View اضافه میکند. نوشتار «سلام Android!» توسط ابزارک TextView نمایش داده میشود. نوشتار «Hello Compose!» توسط عنصر نوشتاری Compose نمایش داده میشود.
همچنین میتوانید ComposeView را مستقیماً در قطعهای اضافه کنید اگر تمام صفحه شما
با Compose ساخته شده باشد، که به شما امکان میدهد از استفاده از فایل طرحبندی XML بهطور کامل اجتناب کنید.
class ExampleFragmentNoXml : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { return ComposeView(requireContext()).apply { // Dispose of the Composition when the view's LifecycleOwner // is destroyed setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed) setContent { MaterialTheme { // In Compose world Text("Hello Compose!") } } } } }
چندین نمونه ComposeView در یک چیدمان
اگر چند عنصر ComposeView در یک چیدمان وجود داشته باشد، هرکدام باید شناسه یکتایی داشته باشند تا savedInstanceState کار کند.
class ExampleFragmentMultipleComposeView : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View = LinearLayout(requireContext()).apply { addView( ComposeView(requireContext()).apply { setViewCompositionStrategy( ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed ) id = R.id.compose_view_x // ... } ) addView(TextView(requireContext())) addView( ComposeView(requireContext()).apply { setViewCompositionStrategy( ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed ) id = R.id.compose_view_y // ... } ) } }
شناسههای ComposeView در فایل res/values/ids.xml تعریف شدهاند:
<resources> <item name="compose_view_x" type="id" /> <item name="compose_view_y" type="id" /> </resources>
پیشدید کردن composable در «ویرایشگر چیدمان»
همچنین میتوانید composable را در «ویرایشگر چیدمان» برای چیدمان XML خود که حاوی ComposeView است پیشدید کنید. با انجام این کار میتوانید ببینید که composable شما در چیدمان ترکیبی Views و Compose چگونه بهنظر میرسد.
فرض کنید میخواهید ترکیبپذیر زیر را در «ویرایشگر چیدمان» نمایش دهید. توجه
داشته باشید که ترکیبپذیرهای حاشیهنویسیشده با @Preview گزینههای خوبی برای پیشدید در
«ویرایشگر چیدمان» هستند.
@Preview @Composable fun GreetingPreview() { Greeting(name = "Android") }
برای نمایش این composable، از مشخصه ابزارهای tools:composableName استفاده کنید و
مقدار آن را روی نام کاملاً واجد شرایط composable برای پیشنمایش در
چیدمان تنظیم کنید.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <androidx.compose.ui.platform.ComposeView android:id="@+id/my_compose_view" tools:composableName="com.example.compose.snippets.interop.InteroperabilityAPIsSnippetsKt.GreetingPreview" android:layout_height="match_parent" android:layout_width="match_parent"/> </LinearLayout>
