คุณสามารถรวมลำดับชั้นการแสดงผลของ Android View ไว้ใน UI ของ Compose ได้ วิธีนี้มีประโยชน์อย่างยิ่งหากคุณต้องการใช้องค์ประกอบ UI ที่ยังไม่พร้อมใช้งานใน Compose เช่น AdView
นอกจากนี้ วิธีนี้ยังช่วยให้คุณนํามุมมองที่กําหนดเองซึ่งอาจออกแบบไว้แล้วกลับมาใช้ใหม่ได้ด้วย
หากต้องการรวมองค์ประกอบมุมมองหรือลำดับชั้น ให้ใช้ Composable 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 ใน Lazy List
หากคุณใช้ AndroidView ในรายการแบบ Lazy (LazyColumn, LazyRow,
Pager ฯลฯ) ให้ลองใช้การโอเวอร์โหลด AndroidView
ที่เปิดตัวในเวอร์ชัน 1.4.0-rc01 การโอเวอร์โหลดนี้ช่วยให้ Compose สามารถนำอินสแตนซ์ View ที่อยู่เบื้องหลังมาใช้ซ้ำได้เมื่อมีการนำการจัดองค์ประกอบที่มีอยู่มาใช้ซ้ำตามเดิม
เช่นเดียวกับกรณีของรายการแบบ Lazy
การโอเวอร์โหลดนี้ของ 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 AndroidFragment เพื่อเพิ่ม Fragment ใน Compose
AndroidFragment มีการจัดการเฉพาะส่วน เช่น การนำ
ส่วนออกเมื่อ Composable ออกจากการเขียน
หากต้องการรวม Fragment ให้ใช้ Composable AndroidFragment
คุณส่งFragmentคลาสไปยังAndroidFragment ซึ่งจะเพิ่มอินสแตนซ์ของคลาสนั้นลงในการคอมโพสิชันโดยตรง AndroidFragment ยังมีออบเจ็กต์ fragmentState เพื่อสร้าง AndroidFragment ที่มีสถานะที่กำหนด arguments เพื่อส่งไปยัง Fragment ใหม่ และการเรียกกลับ onUpdate ที่ให้ Fragment จากการจัดองค์ประกอบ เช่นเดียวกับ Composable บิวท์อินอื่นๆ อีกมากมาย AndroidFragment รับพารามิเตอร์ Modifier ที่คุณใช้ได้ เช่น เพื่อกำหนดตำแหน่งใน Composable ระดับบน
เรียกใช้ AndroidFragment ในการเขียนโดยทำดังนี้
@Composable fun FragmentInComposeExample() { AndroidFragment<MyFragment>() }
การเรียกใช้เฟรมเวิร์ก Android จาก Compose
Compose ทำงานภายในคลาสเฟรมเวิร์กของ Android เช่น โฮสต์ในคลาส Android View เช่น Activity หรือ Fragment และอาจใช้คลาสเฟรมเวิร์ก Android เช่น Context, ทรัพยากรของระบบ Service หรือ BroadcastReceiver
ดูข้อมูลเพิ่มเติมเกี่ยวกับทรัพยากรของระบบได้ที่ทรัพยากรใน Compose
ภาษาของการเรียบเรียง
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") } }
Broadcast Receiver
หากต้องการแสดง 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 */ }
การโต้ตอบอื่นๆ
หากไม่มีฟังก์ชันที่กำหนดไว้สำหรับการโต้ตอบที่คุณต้องการ แนวทางปฏิบัติแนะนำ คือการทำตามหลักเกณฑ์ทั่วไปของ 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) } }