คุณสามารถเพิ่ม UI ที่ใช้ 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!") }
โค้ดนี้มีลักษณะเหมือนกับที่คุณเห็นในแอปเขียนอีเมลเท่านั้น
ViewCompositionStrategy
เป็นเวลา ComposeView
ViewCompositionStrategy
กำหนดว่าควรกำจัดคอมโพสิชันเมื่อใด ค่าเริ่มต้น ViewCompositionStrategy.Default
จะทิ้งคอมโพสิชันเมื่อคอมโพสิชันพื้นฐาน ComposeView
แยกออกจากหน้าต่าง เว้นแต่ว่าจะเป็นส่วนหนึ่งของคอนเทนเนอร์การรวมกลุ่ม เช่น RecyclerView
ในแอป Compose อย่างเดียวที่มีกิจกรรมเดียว ลักษณะการทำงานเริ่มต้นนี้เป็นสิ่งที่คุณต้องการ อย่างไรก็ตาม หากคุณเพิ่ม Compose ลงในโค้ดเบสทีละส่วน ลักษณะการทำงานนี้อาจทำให้ข้อมูลสถานะสูญหายในบางสถานการณ์
หากต้องการเปลี่ยน ViewCompositionStrategy
ให้เรียกใช้เมธอด setViewCompositionStrategy()
แล้วระบุกลยุทธ์อื่น
ตารางด้านล่างสรุปสถานการณ์ต่างๆ ที่คุณสามารถใช้ViewCompositionStrategy
ได้
ViewCompositionStrategy |
คำอธิบายและสถานการณ์การทํางานร่วมกัน |
---|---|
DisposeOnDetachedFromWindow |
ระบบจะทิ้งการคอมโพสเมื่อมีการแยก ComposeView ที่อยู่เบื้องหลังออกจากหน้าต่าง แทนที่ด้วย DisposeOnDetachedFromWindowOrReleasedFromPool .สถานการณ์การทํางานร่วมกัน: * ComposeView ไม่ว่าจะองค์ประกอบเดียวในลําดับชั้นของมุมมอง หรือในบริบทของหน้าจอมุมมอง/เขียนแบบผสม (ไม่ใช่ใน FRG) |
DisposeOnDetachedFromWindowOrReleasedFromPool (ค่าเริ่มต้น) |
คล้ายกับ DisposeOnDetachedFromWindow เมื่อการประพันธ์ไม่ได้อยู่ในคอนเทนเนอร์การรวม เช่น RecyclerView หากอยู่ในคอนเทนเนอร์การรวมกลุ่ม ระบบจะทิ้งรายการนั้นเมื่อคอนเทนเนอร์การรวมกลุ่มแยกออกจากหน้าต่าง หรือเมื่อมีการทิ้งรายการ (เมื่อพูลเต็ม)สถานการณ์การทํางานร่วมกัน: * ComposeView ไม่ว่าจะอยู่ในองค์ประกอบเดียวในลําดับชั้นของ View หรือในบริบทของหน้าจอ View/Compose แบบผสม (ไม่ได้อยู่ใน Fregment)* ComposeView เป็นรายการในคอนเทนเนอร์การรวม เช่น RecyclerView |
DisposeOnLifecycleDestroyed |
ระบบจะทิ้งคอมโพสิชันเมื่อมีการทำลาย Lifecycle ที่ระบุสถานการณ์การผสานรวม * ComposeView ในมุมมองของ Fregment |
DisposeOnViewTreeLifecycleDestroyed |
ระบบจะทิ้งคอมโพสิชันเมื่อมีการทำลาย Lifecycle ที่เป็นของ LifecycleOwner ที่ ViewTreeLifecycleOwner.get ของหน้าต่างถัดไปที่ View แนบอยู่แสดงผลสถานการณ์การทํางานร่วมกัน: * ComposeView ในมุมมองของ Fregment* ComposeView ในมุมมองที่ยังไม่ทราบว่าวงจรของลูกค้าเป็นอย่างไร |
ComposeView
ใน "ส่วนย่อย"
หากต้องการรวมเนื้อหา UI ของ Compose ไว้ในแฟรกเมนต์หรือเลย์เอาต์ View ที่มีอยู่ ให้ใช้ ComposeView
แล้วเรียกใช้เมธอด setContent()
ของ Compose 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 ให้ขยายเลย์เอาต์จาก layout
resource ที่กําหนดใน 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 การแสดงผลนี้แสดงเอาต์พุตของโค้ดที่เพิ่มองค์ประกอบการเขียนในลําดับชั้น UI ของมุมมอง ข้อความ "สวัสดี Android" จะแสดงโดยวิดเจ็ต TextView
ข้อความ "สวัสดี 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>
แสดงตัวอย่างคอมโพเนนต์ที่เขียนด้วย Compose ได้ในเครื่องมือสร้างเลย์เอาต์
นอกจากนี้ คุณยังแสดงตัวอย่างคอมโพสิเบิลภายในเครื่องมือแก้ไขเลย์เอาต์สำหรับเลย์เอาต์ 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>
ขั้นตอนถัดไป
เมื่อทราบ API การทำงานร่วมกันเพื่อใช้ Compose ใน View แล้ว โปรดดูวิธีใช้ View ใน Compose
แนะนำสำหรับคุณ
- หมายเหตุ: ข้อความลิงก์จะแสดงเมื่อ JavaScript ปิดอยู่
- ข้อควรพิจารณาอื่นๆ
- กลยุทธ์การย้ายข้อมูล {:#migration-strategy}
- เปรียบเทียบประสิทธิภาพของฟีเจอร์เขียนและดู