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

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

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

إذا أردت دمج محتوى واجهة مستخدم ميزة "الإنشاء" في جزء أو تنسيق View حالي، استخدِم 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>

في رمز 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
    }
}

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

الشكل 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 tools (الأدوات) و اضبط قيمتها على الاسم المؤهَّل بالكامل للعنصر القابل للتجميع لمعاينته في التنسيق.

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

عنصر قابل للتجميع معروض في &quot;أداة تعديل التنسيق&quot;

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

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