שימוש ב'כתיבה' בתצוגות

אפשר להוסיף ממשק משתמש מבוסס-כתיבה לאפליקציה קיימת שמשתמשת בעיצוב מבוסס-תצוגה.

כדי ליצור מסך חדש שמבוסס על 'כתיבה', צריך קוראים ל-method 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. באפליקציית 'כתיבה' לפעילות יחידה בלבד, התנהגות ברירת המחדל הזו לעומת זאת, אם מוסיפים עוד ועוד 'כתיבה' ההתנהגות הזו עלולה לגרום לאובדן מצב בתרחישים מסוימים.

כדי לשנות את ViewCompositionStrategy, יש להפעיל את setViewCompositionStrategy() ולספק אסטרטגיה אחרת.

הטבלה שבהמשך מסכמת את התרחישים השונים שבהם אפשר להשתמש ViewCompositionStrategy ב:

ViewCompositionStrategy תיאור ותרחיש של יכולת פעולה הדדית
DisposeOnDetachedFromWindow היצירה תימחק לאחר ניתוק ה-ComposeView הבסיסי מהחלון. הגרסה הוחלפה מאז על ידי DisposeOnDetachedFromWindowOrReleasedFromPool.

תרחיש של יכולת פעולה הדדית:

* ComposeView, אם זה הרכיב היחיד בהיררכיית התצוגה, או בהקשר של מסך תצוגה/כתיבה מעורב (לא ב-Fragment).
DisposeOnDetachedFromWindowOrReleasedFromPool (ברירת מחדל) בדומה ל-DisposeOnDetachedFromWindow, כשהיצירה לא נמצאת בקונטיינר למאגר, למשל RecyclerView. אם מאגר התגים כלול במאגר הנתונים שבמאגר, הוא יוסר כשהמאגר עצמו מתנתק מהחלון או כשהפריט נמחק (כלומר כשהמאגר מלא).

תרחיש של יכולת פעולה הדדית:

* ComposeView אם זה הרכיב היחיד בהיררכיית התצוגה, או בהקשר של מסך משולב של תצוגה/פיתוח (לא מקטע).
* ComposeView כפריט בקונטיינר למאגר, כמו RecyclerView.
DisposeOnLifecycleDestroyed היצירה תימחק לאחר שה-Lifecycle שסופק יושמד.

תרחיש של יכולת פעולה הדדית

* ComposeView בתצוגה של מקטע.
DisposeOnViewTreeLifecycleDestroyed היצירה תימחק כאשר Lifecycle שבבעלות LifecycleOwner שהוחזר על ידי ViewTreeLifecycleOwner.get של החלון הבא שאליו התצוגה מצורפת יושמד.

תרחיש פעולה הדדית:

* ComposeView בתצוגה של מקטע.
* ComposeView בתצוגה שבה מחזור החיים עדיין לא ידוע.

ComposeView במקטעים

אם רוצים לשלב את התוכן של ממשק המשתמש של 'כתיבה' במקטע או בתצוגה קיימת פריסה, צריך להשתמש ב-ComposeView וקוראים לו setContent() . ComposeView הוא מכשיר Android View.

אפשר להוסיף את 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() כדי להשתמש בהצעות לכתיבה.

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 הצגת ההיררכיה של ממשק המשתמש. ההודעה "שלום Android!" טקסט מוצג על ידי הווידג'ט TextView. ההודעה "Hello 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>

תוכן קומפוזבילי מוצג בעורך הפריסה

השלבים הבאים

עכשיו, אחרי שאתם מכירים את ממשקי ה-API ליכולת פעולה הדדית לשימוש ב'כתיבה' ב-Views', איך להשתמש בצפיות בכתיבה.