استخدام ميزة "الإنشاء" في طرق العرض

يمكنك إضافة واجهة مستخدم مستندة إلى ميزة "الإنشاء" إلى تطبيق حالي يستخدم تصميمًا مستندًا إلى عنصر عرض.

لإنشاء شاشة جديدة تستند بالكامل إلى 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!")
}

يبدو هذا الرمز تمامًا مثل الرمز الذي يظهر في تطبيق "الإنشاء" فقط.

ViewCompositionStrategy لـ ComposeView

ViewCompositionStrategy يحدِّد وقت إزالة المقطوعة الموسيقية. يؤدي ضبط الإعداد التلقائي، ViewCompositionStrategy.Default، إلى التخلص من المقطوعة الموسيقية عند فصل ComposeView الأساسي عن النافذة، إلا إذا كانت جزءًا من حاوية تجميع مثل RecyclerView. في تطبيق يتضمّن نشاطًا واحدًا يستخدم Compose فقط، يكون هذا السلوك التلقائي هو ما تريده، ولكن إذا كنت تضيف Compose بشكل تدريجي إلى قاعدة بيانات الرموز البرمجية، قد يؤدي هذا السلوك إلى فقدان الحالة في بعض السيناريوهات.

لتغيير ViewCompositionStrategy، استدعِ الطريقة setViewCompositionStrategy() وقدِّم استراتيجية مختلفة.

يلخّص الجدول أدناه السيناريوهات المختلفة التي يمكنك استخدام ViewCompositionStrategy فيها في:

ViewCompositionStrategy الوصف وسيناريو التشغيل التفاعلي
DisposeOnDetachedFromWindow سيتم التخلص من التركيب عند فصل ComposeView الأساسي عن النافذة. تم استبداله منذ ذلك الحين بـ DisposeOnDetachedFromWindowOrReleasedFromPool.

سيناريو التشغيل التفاعلي:

* ComposeView سواء كان العنصر الوحيد في التسلسل الهرمي لعرض المحتوى، أو في سياق شاشة عرض/إنشاء مختلطة (وليس في المقتطف).
DisposeOnDetachedFromWindowOrReleasedFromPool (الإعداد التلقائي) على غرار السمة DisposeOnDetachedFromWindow، عندما لا تكون المقطوعة الموسيقية في حاوية تجميع، مثل RecyclerView. إذا كان العنصر في حاوية تجميع، سيتم التخلص منه عند فصل حاوية التجميع نفسها عن النافذة أو عند تجاهل العنصر (أي عندما تكون الحاوية ممتلئة).

سيناريو التشغيل التفاعلي:

* ComposeView سواء كان العنصر الوحيد في التسلسل الهرمي لعرض العناصر أو في سياق شاشة عرض/إنشاء مختلطة (وليس في "الجزء").
* ComposeView كعنصر في حاوية تجميع مثل RecyclerView
DisposeOnLifecycleDestroyed سيتم التخلص من التركيب عند إتلاف Lifecycle المقدَّمة.

سيناريو التشغيل التفاعلي

* ComposeView في عرض "العنصر"
DisposeOnViewTreeLifecycleDestroyed سيتم التخلص من التركيب عند إتلاف Lifecycle الذي يملكه LifecycleOwner الذي تم إرجاعه بواسطة ViewTreeLifecycleOwner.get من النافذة التالية التي يتم إرفاق "العرض" بها.

سيناريو التشغيل التفاعلي:

* ComposeView في عرض "العنصر"
* ComposeView في عرض لا يُعرف فيه مسار الإحالة الناجحة بعد

ComposeView في "الأجزاء"

إذا أردت دمج محتوى واجهة المستخدم في Compose في جزء أو في تنسيق عرض حالي، استخدِم ComposeView واستدعِ الطريقة setContent(). ‫ComposeView هو View لنظام التشغيل Android.

يمكنك وضع ComposeView بتنسيق XML مثل أي View آخر:

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

يمكنك تضخيم التنسيق من مورد التنسيق المحدد في XML في رمز مصدر Kotlin. بعد ذلك، احصل على 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
    }
}

عنصرا نص مختلفان قليلاً، أحدهما فوق الآخر

الشكل 1. يعرض هذا الرمز الناتج عن الرمز الذي يضيف عناصر Compose في التسلسل الهرمي لواجهة مستخدم View. يتم عرض النص "مرحبًا Android" من خلال أداة TextView. يتم عرض النص "مرحبًا 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>

معاينة العناصر القابلة للتجميع في "أداة تعديل التنسيق"

يمكنك أيضًا معاينة العناصر القابلة للتجميع ضمن "أداة تصميم التنسيقات" لتنسيق XML الذي يحتوي على ComposeView. يتيح لك ذلك الاطّلاع على شكل العناصر القابلة للتجميع ضمن تنسيق مختلط للعروض والتنسيقات.

لنفترض أنك تريد عرض العناصر التالية القابلة للإنشاء في "محرِّر التنسيق". يُرجى العِلم أنّ العناصر القابلة للإنشاء التي تمت إضافة تعليقات توضيحية إليها باستخدام @Preview هي اقتراحات جيدة لمعاينتها في "محرِّر التنسيق".

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

لعرض هذا قابل للإنشاء، استخدِم سمة أدوات tools:composableName واضبط قيمتها على الاسم المؤهّل بالكامل للعنصر القابل للإنشاء لمعاينته في التنسيق.

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

عرض قابل للتعديل ضمن محرِّر التنسيق

الخطوات التالية

بعد أن تعرّفت على واجهات برمجة التطبيقات للتشغيل التفاعلي لاستخدام Compose في Views، يمكنك الاطّلاع على كيفية استخدام Views في Compose.