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

می‌توانید رابط کاربری مبتنی بر Compose را به یک برنامه موجود که از طراحی مبتنی بر View استفاده می‌کند، اضافه کنید.

برای ایجاد یک صفحه جدید کاملاً مبتنی بر نوشتن، از فعالیت خود بخواهید متد 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!")
}

این کد دقیقاً شبیه چیزی است که در یک برنامه فقط نوشتن پیدا می کنید.

ViewCompositionStrategy برای ComposeView

ViewCompositionStrategy تعیین می کند که ترکیب باید چه زمانی از بین برود. پیش‌فرض، ViewCompositionStrategy.Default ، وقتی ComposeView زیربنایی از پنجره جدا می‌شود، Composition را حذف می‌کند، مگر اینکه بخشی از یک کانتینر ترکیبی مانند RecyclerView باشد. در یک برنامه فقط برای نوشتن یک فعالیت، این رفتار پیش‌فرض همان چیزی است که می‌خواهید، اما اگر به‌صورت تدریجی Compose را در پایگاه کد خود اضافه کنید، این رفتار ممکن است در برخی از سناریوها باعث از دست دادن حالت شود.

برای تغییر ViewCompositionStrategy ، متد setViewCompositionStrategy() را فراخوانی کنید و یک استراتژی متفاوت ارائه دهید.

جدول زیر سناریوهای مختلفی را که می توانید از ViewCompositionStrategy در آنها استفاده کنید، خلاصه می کند:

ViewCompositionStrategy شرح و سناریوی interop
DisposeOnDetachedFromWindow هنگامی که ComposeView زیرین از پنجره جدا شود، Composition حذف خواهد شد. از آن زمان توسط DisposeOnDetachedFromWindowOrReleasedFromPool جایگزین شده است.

سناریوی Interop:

* ComposeView چه تنها عنصر در سلسله مراتب View باشد یا در زمینه یک صفحه نمایش مختلط View/Compose (نه در Fragment).
DisposeOnDetachedFromWindowOrReleasedFromPool ( پیش فرض ) مشابه DisposeOnDetachedFromWindow ، زمانی که Composition در یک محفظه جمع‌آوری نیست، مانند RecyclerView . اگر در ظرف جمع‌آوری باشد، زمانی که ظرف جمع‌آوری خود از پنجره جدا می‌شود، یا زمانی که مورد در حال دور انداختن است (یعنی وقتی استخر پر است) دفع می‌شود.

سناریوی Interop:

* ComposeView چه تنها عنصر در سلسله مراتب View باشد یا در زمینه یک صفحه نمایش مختلط View/Compose (نه در Fragment).
* ComposeView به عنوان یک آیتم در یک کانتینر ترکیبی مانند RecyclerView .
DisposeOnLifecycleDestroyed هنگامی که Lifecycle ارائه شده از بین برود، ترکیب حذف خواهد شد.

سناریوی Interop

* ComposeView در نمای قطعه.
DisposeOnViewTreeLifecycleDestroyed هنگامی که Lifecycle متعلق به LifecycleOwner که توسط ViewTreeLifecycleOwner.get از پنجره بعدی که View به آن متصل است، بازگردانده شود، از بین می رود.

سناریوی Interop:

* ComposeView در نمای قطعه.
* 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 دریافت کنید، یک استراتژی Composition را تنظیم کنید که برای View میزبان بهترین عملکرد را داشته باشد و برای استفاده از Compose setContent() را فراخوانی کنید.

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
    }
}

همچنین، می‌توانید از view binding برای به دست آوردن ارجاع به ComposeView با ارجاع به کلاس binding تولید شده برای فایل طرح‌بندی 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
    }
}

دو عنصر متنی کمی متفاوت، یکی بالای دیگری

شکل 1. این خروجی کدی را نشان می دهد که عناصر Compose را در سلسله مراتب View UI اضافه می کند. "سلام اندروید!" متن توسط ویجت TextView نمایش داده می شود. "Hello Compose!" متن توسط یک عنصر متن Compose نمایش داده می شود.

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

پیش نمایش composables در Layout Editor

همچنین می‌توانید برای طرح‌بندی XML خود که حاوی ComposeView است، composable‌ها را در ویرایشگر Layout پیش‌نمایش کنید. انجام این کار به شما امکان می‌دهد ببینید که اجزای سازنده شما در یک طرح‌بندی ترکیبی Views و Compose چگونه به نظر می‌رسند.

فرض کنید می‌خواهید ترکیب‌بندی زیر را در ویرایشگر طرح‌بندی نمایش دهید. توجه داشته باشید که composable هایی که با @Preview حاشیه نویسی شده اند، کاندیدهای خوبی برای پیش نمایش در Layout Editor هستند.

@Preview
@Composable
fun GreetingPreview() {
    Greeting(name = "Android")
}

برای نمایش این composable، از ویژگی tools:composableName tools استفاده کنید و مقدار آن را روی نام کاملا واجد شرایط 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>

Composable در ویرایشگر طرح نمایش داده می شود

مراحل بعدی

اکنون که APIهای قابلیت همکاری برای استفاده از Compose در Views را می‌شناسید، نحوه استفاده از Views در Compose را بیاموزید.

{% کلمه به کلمه %} {% آخر کلمه %} {% کلمه به کلمه %} {% آخر کلمه %}