คุณสามารถเพิ่ม UI แบบ 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!") }
โค้ดนี้มีลักษณะเหมือนกับที่คุณเห็นในแอป Compose เท่านั้น
ViewCompositionStrategy
เป็นเวลา ComposeView
ViewCompositionStrategy
กำหนดเวลาที่ควรกำจัดองค์ประกอบ ค่าเริ่มต้น
ViewCompositionStrategy.Default
กำจัดองค์ประกอบเมื่อองค์ประกอบ
ComposeView
ถอดออกจากหน้าต่าง เว้นแต่ว่าจะเป็นส่วนหนึ่งของคอนเทนเนอร์ร่วม เช่น
RecyclerView
ลักษณะการทำงานเริ่มต้นในแอปสำหรับเขียนเฉพาะกิจกรรมเดียวคือ
สิ่งที่คุณต้องการ อย่างไรก็ตาม หากคุณเพิ่ม Compose ลงใน
โค้ดเบส การทำงานนี้อาจทำให้สถานะสูญหายในบางสถานการณ์
หากต้องการเปลี่ยน ViewCompositionStrategy
ให้เรียก setViewCompositionStrategy()
และระบุกลยุทธ์อื่น
ตารางด้านล่างจะสรุปสถานการณ์ต่างๆ ที่คุณใช้ได้
ViewCompositionStrategy
ใน:
ViewCompositionStrategy |
คำอธิบายและสถานการณ์การทำงานร่วมกัน |
---|---|
DisposeOnDetachedFromWindow |
ระบบจะกำจัดองค์ประกอบเมื่อถอด ComposeView ที่สำคัญออกจากหน้าต่าง แล้วก็ถูกแทนที่โดย DisposeOnDetachedFromWindowOrReleasedFromPool สถานการณ์การทำงานร่วมกัน: * ComposeView ไม่ว่าจะเป็นองค์ประกอบเดียวในลำดับชั้นการแสดงผล หรือในบริบทของหน้าจอมุมมอง/การเขียนแบบผสม (ไม่ใช่ใน Fragment) |
DisposeOnDetachedFromWindowOrReleasedFromPool (ค่าเริ่มต้น) |
เช่นเดียวกับ DisposeOnDetachedFromWindow เมื่อการเรียบเรียงไม่ได้อยู่ในคอนเทนเนอร์การรวม เช่น RecyclerView หากอยู่ในคอนเทนเนอร์ร่วม ระบบจะกำจัดเมื่อคอนเทนเนอร์ร่วมออกจากหน้าต่าง หรือเมื่อมีการทิ้งรายการ (เช่น เมื่อพูลเต็ม)สถานการณ์การทำงานร่วมกัน: * ComposeView ไม่ว่าจะเป็นองค์ประกอบเดียวในลำดับชั้นการดู หรือในบริบทของหน้าจอมุมมอง/เขียนแบบผสม (ไม่ใช่ Fragment)* ComposeView เป็นรายการในคอนเทนเนอร์ร่วม เช่น RecyclerView |
DisposeOnLifecycleDestroyed |
ระบบจะกำจัดองค์ประกอบเมื่อ Lifecycle ที่ระบุถูกทำลายสถานการณ์การทำงานร่วมกัน * ComposeView ในมุมมองของ Fragment |
DisposeOnViewTreeLifecycleDestroyed |
ระบบจะกำจัดองค์ประกอบเมื่อ Lifecycle ของ LifecycleOwner ซึ่งแสดงผลโดย ViewTreeLifecycleOwner.get ของหน้าต่างถัดไปที่มีการเชื่อมต่อมุมมองถูกทำลายสถานการณ์การทำงานร่วมกัน: * ComposeView ในมุมมองของ Fragment* ComposeView ในข้อมูลพร็อพเพอร์ตี้ที่ยังไม่ทราบวงจร |
ComposeView
ใน Fragment
ถ้าคุณต้องการรวมเนื้อหา UI ของ Compose ไว้ในส่วนย่อยหรือมุมมองที่มีอยู่
เลย์เอาต์ ให้ใช้ 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 ไว้ในไฟล์
ดูลำดับชั้นของ UI หน้าต่าง "สวัสดี Android!" ข้อความที่แสดงโดย
วิดเจ็ต TextView
หน้าต่าง "สวัสดีเขียน!" ข้อความที่แสดงโดย
เขียนองค์ประกอบของข้อความ
คุณยังรวม 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>
แสดงตัวอย่าง Composable ในเครื่องมือแก้ไขเลย์เอาต์
นอกจากนี้คุณยังแสดงตัวอย่าง Composable ภายในเครื่องมือแก้ไขเลย์เอาต์สำหรับเลย์เอาต์ XML ได้ด้วย
ที่มี ComposeView
การดำเนินการนี้จะช่วยให้คุณเห็นลักษณะของ Composable
ภายในมุมมองแบบผสมและเลย์เอาต์การเขียน
สมมติว่าคุณต้องการแสดง Composable ต่อไปนี้ในเครื่องมือแก้ไขการออกแบบ หมายเหตุ
ที่ Composable ที่มีคำอธิบายประกอบ @Preview
เป็นตัวเลือกที่ดีในการดูตัวอย่างใน
เครื่องมือแก้ไขเลย์เอาต์
@Preview @Composable fun GreetingPreview() { Greeting(name = "Android") }
หากต้องการแสดง Composable นี้ ให้ใช้แอตทริบิวต์เครื่องมือ tools:composableName
และ
ตั้งค่าเป็นชื่อที่มีคุณสมบัติครบถ้วนของ 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>
ขั้นตอนถัดไป
เมื่อคุณทราบ API ที่ทำงานร่วมกันเพื่อใช้ Compose ใน View แล้ว โปรดเรียนรู้ วิธีใช้ Views in Compose
แนะนำสำหรับคุณ
- หมายเหตุ: ข้อความลิงก์จะแสดงเมื่อ JavaScript ปิดอยู่
- ข้อควรพิจารณาอื่นๆ
- กลยุทธ์การย้ายข้อมูล {:#Migration-strategy}
- เปรียบเทียบประสิทธิภาพของการเขียนและการดู