คุณสามารถใส่ลําดับชั้นของมุมมอง Android ใน UI ของ Compose ได้ แนวทางนี้จะมีประโยชน์อย่างยิ่งหากคุณต้องการใช้องค์ประกอบ UI ที่ยังไม่มีให้ใช้งานในเครื่องมือเขียน เช่น AdView
วิธีนี้ยังช่วยให้คุณนํามุมมองที่กําหนดเองซึ่งอาจออกแบบไว้มาใช้ซ้ำได้ด้วย
หากต้องการรวมองค์ประกอบมุมมองหรือลําดับชั้น ให้ใช้ AndroidView
composable AndroidView
ได้รับค่า Lambda ที่แสดงผล View
AndroidView
ยังมี update
การเรียกกลับที่จะเรียกใช้เมื่อมีการขยายมุมมอง AndroidView
จะจัดเรียงใหม่ทุกครั้งที่มีการเปลี่ยนแปลงState
ที่อ่านภายในการเรียกกลับ AndroidView
เช่นเดียวกับคอมโพสิเบิลในตัวอื่นๆ อีกหลายรายการ จะใช้พารามิเตอร์ Modifier
ที่สามารถใช้เพื่อตั้งค่าตำแหน่งในคอมโพสิเบิลหลักได้
@Composable fun CustomView() { var selectedItem by remember { mutableStateOf(0) } // Adds view to Compose AndroidView( modifier = Modifier.fillMaxSize(), // Occupy the max size in the Compose UI tree factory = { context -> // Creates view MyView(context).apply { // Sets up listeners for View -> Compose communication setOnClickListener { selectedItem = 1 } } }, update = { view -> // View's been inflated or state read in this block has been updated // Add logic here if necessary // As selectedItem is read here, AndroidView will recompose // whenever the state changes // Example of Compose -> View communication view.selectedItem = selectedItem } ) } @Composable fun ContentExample() { Column(Modifier.fillMaxSize()) { Text("Look at this CustomView!") CustomView() } }
AndroidView
ที่มี View Binding
หากต้องการฝังเลย์เอาต์ XML ให้ใช้ AndroidViewBinding
API ซึ่งมาจากไลบรารี androidx.compose.ui:ui-viewbinding
โดยโปรเจ็กต์ต้องเปิดใช้การเชื่อมโยงมุมมอง
@Composable fun AndroidViewBindingExample() { AndroidViewBinding(ExampleLayoutBinding::inflate) { exampleView.setBackgroundColor(Color.GRAY) } }
AndroidView
ในรายการแบบเลื่อน
หากคุณใช้ AndroidView
ในรายการแบบ Lazy (LazyColumn
, LazyRow
,
Pager
ฯลฯ) ให้ลองใช้การโอเวอร์โหลด AndroidView
ที่เปิดตัวในเวอร์ชัน 1.4.0-rc01 การโอเวอร์โหลดนี้ช่วยให้ Compose ใช้อินสแตนซ์ View
ที่อยู่เบื้องหลังซ้ำได้เมื่อใช้การคอมโพสิชันที่มีซ้ำตามที่เป็นอยู่สำหรับรายการแบบ Lazy
การโอเวอร์โหลด AndroidView
นี้จะเพิ่มพารามิเตอร์อีก 2 รายการ ได้แก่
onReset
- เรียกใช้การเรียกกลับเพื่อส่งสัญญาณว่าView
กำลังจะนํามาใช้ซ้ำ ค่านี้ต้องไม่เท่ากับ Null เพื่อเปิดใช้การนํามุมมองมาใช้ซ้ำonRelease
(ไม่บังคับ) - การเรียกกลับที่เรียกให้แสดงสัญญาณว่าView
ออกจากการเรียบเรียงแล้วและจะไม่นํากลับมาใช้อีก
@OptIn(ExperimentalComposeUiApi::class) @Composable fun AndroidViewInLazyList() { LazyColumn { items(100) { index -> AndroidView( modifier = Modifier.fillMaxSize(), // Occupy the max size in the Compose UI tree factory = { context -> MyView(context) }, update = { view -> view.selectedItem = index }, onReset = { view -> view.clear() } ) } } }
ข้อมูลโค้ดใน Compose
ใช้คอมโพสิเบิล AndroidViewBinding
เพื่อเพิ่ม Fragment
ในคอมโพสิชัน
AndroidViewBinding
มีการจัดการเฉพาะสำหรับแฟรกเมนต์ เช่น การนำแฟรกเมนต์ออกเมื่อคอมโพสิเบิลออกจากการคอมโพสิชัน
โดยให้ทำดังนี้ ขยาย XML ที่มี FragmentContainerView
เป็นตัวยึดสำหรับ Fragment
ตัวอย่างเช่น หากได้กําหนด my_fragment_layout.xml
แล้ว คุณจะใช้โค้ดแบบนี้ได้ขณะแทนที่แอตทริบิวต์ XML android:name
ด้วยชื่อคลาสของ Fragment
<androidx.fragment.app.FragmentContainerView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/fragment_container_view" android:layout_width="match_parent" android:layout_height="match_parent" android:name="com.example.compose.snippets.interop.MyFragment" />
ขยายข้อมูลโค้ดนี้ใน "เขียน" ดังนี้
@Composable fun FragmentInComposeExample() { AndroidViewBinding(MyFragmentLayoutBinding::inflate) { val myFragment = fragmentContainerView.getFragment<MyFragment>() // ... } }
หากต้องใช้หลายข้อมูลโค้ดในเลย์เอาต์เดียวกัน โปรดตรวจสอบว่าคุณได้กำหนดรหัสที่ไม่ซ้ำกันสำหรับ FragmentContainerView
แต่ละรายการแล้ว
การเรียกใช้เฟรมเวิร์ก Android จาก Compose
Compose ทำงานภายในคลาสเฟรมเวิร์ก Android เช่น โฮสต์ในคลาส Android View เช่น Activity
หรือ Fragment
และอาจใช้คลาสเฟรมเวิร์ก Android เช่น Context
, ทรัพยากรของระบบ, Service
หรือ BroadcastReceiver
ดูข้อมูลเพิ่มเติมเกี่ยวกับทรัพยากรของระบบได้ที่ทรัพยากรในคอมโพซ
องค์ประกอบในท้องถิ่น
คลาส CompositionLocal
ช่วยให้ส่งข้อมูลได้โดยไม่ระบุผ่านฟังก์ชันคอมโพสิเบิล โดยปกติแล้วจะมีค่าในโหนดหนึ่งของต้นไม้ UI ค่าดังกล่าวสามารถใช้โดยองค์ประกอบย่อยแบบคอมโพสิเบิลได้โดยไม่ต้องประกาศ CompositionLocal
ว่าเป็นพารามิเตอร์ในฟังก์ชันแบบคอมโพสิเบิล
CompositionLocal
ใช้เพื่อเผยแพร่ค่าสำหรับประเภทเฟรมเวิร์ก Android ใน Compose เช่น Context
, Configuration
หรือ View
ที่โฮสต์โค้ด Compose ไว้กับ LocalContext
, LocalConfiguration
หรือ LocalView
ที่เกี่ยวข้อง
โปรดทราบว่าคลาส CompositionLocal
จะมี Local
นำหน้าเพื่อให้ค้นพบได้ง่ายขึ้นด้วยการเติมข้อความอัตโนมัติใน IDE
เข้าถึงค่าปัจจุบันของ CompositionLocal
โดยใช้พร็อพเพอร์ตี้ current
ตัวอย่างเช่น โค้ดด้านล่างแสดงข้อความโทสต์โดยระบุ LocalContext.current
ลงในเมธอด Toast.makeToast
@Composable fun ToastGreetingButton(greeting: String) { val context = LocalContext.current Button(onClick = { Toast.makeText(context, greeting, Toast.LENGTH_SHORT).show() }) { Text("Greet") } }
ดูตัวอย่างที่สมบูรณ์ยิ่งขึ้นได้ในส่วนกรณีศึกษา: BroadcastReceiver ที่ท้ายเอกสารนี้
การโต้ตอบอื่นๆ
หากไม่มีการกำหนดยูทิลิตีสำหรับการโต้ตอบที่ต้องการ แนวทางปฏิบัติแนะนำคือการปฏิบัติตามหลักเกณฑ์ทั่วไปของ Compose ซึ่งก็คือข้อมูลไหลลง เหตุการณ์ไหลขึ้น (ดูรายละเอียดเพิ่มเติมในการคิดใน Compose) เช่น คอมโพสิเบิลนี้จะเปิดใช้งานกิจกรรมอื่น
class OtherInteractionsActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // get data from savedInstanceState setContent { MaterialTheme { ExampleComposable(data, onButtonClick = { startActivity(Intent(this, MyActivity::class.java)) }) } } } } @Composable fun ExampleComposable(data: DataExample, onButtonClick: () -> Unit) { Button(onClick = onButtonClick) { Text(data.title) } }
กรณีศึกษา: ตัวรับสัญญาณการออกอากาศ
ตัวอย่างที่ใกล้เคียงกับการใช้งานจริงมากขึ้นของฟีเจอร์ที่คุณอาจต้องการย้ายข้อมูลหรือติดตั้งใช้งานใน Compose และเพื่อแสดง CompositionLocal
และผลข้างเคียง สมมติว่าต้องลงทะเบียน BroadcastReceiver
จากฟังก์ชันคอมโพสิเบิล
โซลูชันนี้ใช้ประโยชน์จาก LocalContext
เพื่อใช้บริบทปัจจุบัน และ rememberUpdatedState
และผลข้างเคียงของ DisposableEffect
@Composable fun SystemBroadcastReceiver( systemAction: String, onSystemEvent: (intent: Intent?) -> Unit ) { // Grab the current context in this part of the UI tree val context = LocalContext.current // Safely use the latest onSystemEvent lambda passed to the function val currentOnSystemEvent by rememberUpdatedState(onSystemEvent) // If either context or systemAction changes, unregister and register again DisposableEffect(context, systemAction) { val intentFilter = IntentFilter(systemAction) val broadcast = object : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { currentOnSystemEvent(intent) } } context.registerReceiver(broadcast, intentFilter) // When the effect leaves the Composition, remove the callback onDispose { context.unregisterReceiver(broadcast) } } } @Composable fun HomeScreen() { SystemBroadcastReceiver(Intent.ACTION_BATTERY_CHANGED) { batteryStatus -> val isCharging = /* Get from batteryStatus ... */ true /* Do something if the device is charging */ } /* Rest of the HomeScreen */ }
ขั้นตอนถัดไป
ตอนนี้คุณทราบเกี่ยวกับ API การทํางานร่วมกันเมื่อใช้การเขียนในมุมมองและในทางกลับกันแล้ว โปรดดูข้อมูลเพิ่มเติมในหน้าข้อควรพิจารณาอื่นๆ
แนะนำสำหรับคุณ
- หมายเหตุ: ข้อความลิงก์จะแสดงเมื่อ JavaScript ปิดอยู่
- ข้อควรพิจารณาอื่นๆ
- ผลข้างเคียงในโหมดเขียน
- ข้อมูลระดับที่กําหนดในเครื่องด้วย CompositionLocal