คุณสามารถรวมลำดับชั้นการแสดงผลของ Android View ไว้ใน UI ของ Compose ได้ วิธีนี้มีประโยชน์อย่างยิ่งหากคุณต้องการใช้องค์ประกอบ UI ที่ยังไม่มีใน
Compose เช่น
AdView
นอกจากนี้ วิธีนี้ยังช่วยให้คุณนำมุมมองที่กำหนดเองซึ่งคุณอาจออกแบบไว้แล้วกลับมาใช้ซ้ำได้ด้วย
หากต้องการรวมองค์ประกอบหรือลำดับชั้นของ View ให้ใช้ AndroidView
Composable AndroidView จะรับ Lambda ที่แสดงผล
View นอกจากนี้ AndroidView ยังมี Callback update ที่เรียกใช้เมื่อมีการขยาย View AndroidView จะทำการ Recompose ทุกครั้งที่ State ที่อ่านภายใน Callback เปลี่ยนไป AndroidViewจะใช้พารามิเตอร์ Modifier ซึ่งคุณสามารถใช้เพื่อกำหนดตำแหน่งใน Composable หลักได้ เช่นเดียวกับ Composable บิวท์อินอื่นๆ อีกมากมาย
@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 ที่มีการเชื่อมโยง View
หากต้องการฝังเลย์เอาต์ XML ให้ใช้
AndroidViewBinding
API ซึ่งมีให้โดยไลบรารี androidx.compose.ui:ui-viewbinding หากต้องการทำเช่นนี้ โปรเจ็กต์ต้องเปิดใช้ การเชื่อมโยง View
@Composable fun AndroidViewBindingExample() { AndroidViewBinding(ExampleLayoutBinding::inflate) { exampleView.setBackgroundColor(Color.GRAY) } }
AndroidView ในรายการ Lazy
หากคุณใช้ AndroidView ในรายการ Lazy (LazyColumn, LazyRow,
Pager, ฯลฯ) ให้ลองใช้การโอเวอร์โหลด AndroidView
ที่เปิดตัวในเวอร์ชัน 1.4.0-rc01 การโอเวอร์โหลดนี้ช่วยให้ Compose นำอินสแตนซ์ View พื้นฐานกลับมาใช้ซ้ำได้เมื่อมีการนำการเรียบเรียงที่มีอยู่กลับมาใช้ซ้ำ ซึ่งเป็นกรณีของรายการ Lazy
AndroidView เวอร์ชันโอเวอร์โหลดนี้จะเพิ่มพารามิเตอร์อีก 2 รายการ ดังนี้
onReset- Callback ที่เรียกใช้เพื่อส่งสัญญาณว่าระบบกำลังจะนำViewกลับมาใช้ซ้ำ พารามิเตอร์นี้ต้องไม่ใช่ Null เพื่อเปิดใช้การนำ View กลับมาใช้ซ้ำonRelease(ไม่บังคับ) - Callback ที่เรียกใช้เพื่อส่งสัญญาณว่า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 มีการจัดการเฉพาะ Fragment เช่น การนำ Fragment ออกเมื่อ Composable ออกจากการเรียบเรียง
หากต้องการรวม Fragment ให้ใช้ AndroidFragment
Composable คุณส่งคลาส Fragment ไปยัง AndroidFragment ซึ่งจะเพิ่ม
อินสแตนซ์ของคลาสดังกล่าวลงในการเรียบเรียงโดยตรง นอกจากนี้ AndroidFragment ยังมีออบเจ็กต์ fragmentState เพื่อสร้าง AndroidFragment ที่มีสถานะที่กำหนด arguments เพื่อส่งไปยัง Fragment ใหม่ และ Callback onUpdate ที่ให้ Fragment จากการเรียบเรียง AndroidFragment ยอมรับพารามิเตอร์ Modifier ซึ่งคุณสามารถใช้เพื่อกำหนดตำแหน่งใน Composable หลักได้ เช่นเดียวกับ Composable บิวท์อินอื่นๆ อีกมากมาย
เรียก AndroidFragment ใน Compose ดังนี้
@Composable fun FragmentInComposeExample() { AndroidFragment<MyFragment>() }
การเรียกใช้เฟรมเวิร์ก Android จาก Compose
Compose ทำงานภายในคลาสเฟรมเวิร์ก Android เช่น โฮสต์ในคลาส Android View เช่น Activity หรือ Fragment และอาจใช้คลาสเฟรมเวิร์ก Android เช่น Context, ทรัพยากรระบบ, Service หรือ BroadcastReceiver
ดูข้อมูลเพิ่มเติมเกี่ยวกับทรัพยากรระบบได้ที่ ทรัพยากรใน Compose
Composition Local
CompositionLocal
คลาสอนุญาตให้ส่งข้อมูลผ่านฟังก์ชัน Composable โดยนัย โดยปกติแล้วจะมีการระบุค่าในโหนดหนึ่งของแผนผัง UI องค์ประกอบย่อยที่เป็น Composable สามารถใช้ค่านั้นได้โดยไม่ต้องประกาศ CompositionLocal เป็นพารามิเตอร์ในฟังก์ชันที่ประกอบกันได้
CompositionLocal ใช้เพื่อเผยแพร่ค่าสำหรับประเภทเฟรมเวิร์ก Android ใน
Compose เช่น Context, Configuration หรือ View ที่โฮสต์โค้ด Compose
ด้วย
LocalContext,
LocalConfiguration,
หรือ
LocalView ที่เกี่ยวข้อง
โปรดทราบว่าคลาส CompositionLocal จะมีคำนำหน้าเป็น Local เพื่อให้
ค้นพบได้ง่ายขึ้นด้วยการเติมข้อความอัตโนมัติใน IDE
เข้าถึงค่าปัจจุบันของ CompositionLocal โดยใช้พร็อพเพอร์ตี้ current ตัวอย่างเช่น โค้ดด้านล่างจะแสดงข้อความ Toast โดยระบุ 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 นี้จะเปิดใช้ Activity อื่น
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) } }