คุณสามารถใส่ลำดับชั้นของ Android View ใน UI ของ Compose ได้ แนวทางนี้มีประโยชน์อย่างยิ่งหากคุณต้องการใช้องค์ประกอบ UI ที่ยังไม่พร้อมใช้งานใน Compose เช่น AdView
นอกจากนี้ วิธีนี้ยังช่วยให้คุณนํามุมมองที่กําหนดเองซึ่งอาจออกแบบไว้แล้วกลับมาใช้ใหม่ได้ด้วย
หากต้องการรวมองค์ประกอบมุมมองหรือลำดับชั้น ให้ใช้ AndroidView
ที่ประกอบได้ AndroidView
จะส่งผ่าน Lambda ที่แสดงผล View
AndroidView
ยังมี update
callback ที่เรียกใช้เมื่อขยายมุมมองด้วย AndroidView
จะประกอบใหม่
เมื่อใดก็ตามที่State
อ่านภายในการเปลี่ยนแปลงของโค้ดเรียกกลับ AndroidView
เช่นเดียวกับ
Composables อื่นๆ ในตัว จะใช้พารามิเตอร์ Modifier
ซึ่งใช้เพื่อตั้งค่าตำแหน่งใน Composables ระดับบนได้ เป็นต้น
@Composable fun CustomView() { var selectedItem by remember { mutableIntStateOf(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
ด้วยการเชื่อมโยงมุมมอง
หากต้องการฝังเลย์เอาต์ XML ให้ใช้ API
AndroidViewBinding
ซึ่งมีให้โดยไลบรารี 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 List
การโอเวอร์โหลดนี้ของ AndroidView
จะเพิ่มพารามิเตอร์อีก 2 รายการ ดังนี้
onReset
- การเรียกกลับที่เรียกใช้เพื่อส่งสัญญาณว่ากำลังจะนำView
กลับมาใช้ซ้ำ ต้องไม่เป็น Null เพื่อเปิดใช้การนำ View กลับมาใช้ซ้ำonRelease
(ไม่บังคับ) - การเรียกกลับที่เรียกใช้เพื่อส่งสัญญาณว่าView
ออกจากการเรียบเรียงเพลงแล้วและจะไม่นำกลับมาใช้ซ้ำอีก
@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() } ) } } }
Fragment ใน Compose
ใช้ Composable AndroidViewBinding
เพื่อเพิ่ม Fragment
ใน Compose
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" />
ขยาย Fragment นี้ใน Compose ดังนี้
@Composable fun FragmentInComposeExample() { AndroidViewBinding(MyFragmentLayoutBinding::inflate) { val myFragment = fragmentContainerView.getFragment<MyFragment>() // ... } }
หากต้องการใช้ Fragment หลายรายการในเลย์เอาต์เดียวกัน ให้ตรวจสอบว่าคุณได้
กำหนดรหัสที่ไม่ซ้ำกันสำหรับแต่ละ FragmentContainerView
แล้ว
การเรียกใช้เฟรมเวิร์ก Android จาก Compose
Compose ทำงานภายในคลาสเฟรมเวิร์กของ Android เช่น โฮสต์ในคลาส Android View เช่น Activity
หรือ Fragment
และอาจใช้คลาสเฟรมเวิร์ก Android เช่น Context
, ทรัพยากรของระบบ Service
หรือ BroadcastReceiver
ดูข้อมูลเพิ่มเติมเกี่ยวกับทรัพยากรของระบบได้ที่ทรัพยากรใน Compose
Composition Locals
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") } }
ดูตัวอย่างที่สมบูรณ์ยิ่งขึ้นได้ในส่วนกรณีศึกษา: BroadcastReceivers ที่ตอนท้ายของเอกสารนี้
การโต้ตอบอื่นๆ
หากไม่มีฟังก์ชันที่กำหนดไว้สำหรับการโต้ตอบที่คุณต้องการ แนวทางปฏิบัติแนะนำ คือการทำตามหลักเกณฑ์ทั่วไปของ Compose ข้อมูลไหลลง เหตุการณ์ไหลขึ้น (อธิบายอย่างละเอียดในการคิด ใน Compose) ตัวอย่างเช่น composable นี้ จะเปิดกิจกรรมอื่น
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) } }
กรณีศึกษา: Broadcast Receiver
เพื่อดูตัวอย่างฟีเจอร์ที่สมจริงมากขึ้นซึ่งคุณอาจต้องการย้ายข้อมูลหรือนำไปใช้ใน 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 การทำงานร่วมกันเมื่อใช้ Compose ใน Views และในทางกลับกันแล้ว โปรดไปที่หน้าข้อควรพิจารณาอื่นๆ เพื่อดูข้อมูลเพิ่มเติม
แนะนำสำหรับคุณ
- หมายเหตุ: ข้อความลิงก์จะแสดงเมื่อ JavaScript ปิดอยู่
- ข้อควรพิจารณาอื่นๆ
- ผลข้างเคียงในฟีเจอร์เขียน
- ข้อมูลที่กำหนดขอบเขตในเครื่องด้วย CompositionLocal