Bạn có thể đưa một hệ phân cấp view Android vào Giao diện người dùng của Compose. Phương pháp này đặc biệt hữu ích nếu bạn muốn sử dụng các thành phần trên giao diện người dùng chưa có trong Compose, chẳng hạn như AdView.
Phương pháp này cũng cho phép bạn tái sử dụng các khung hiển thị tuỳ chỉnh mà bạn đã thiết kế.
Để gộp thêm một phần tử hoặc một hệ thành phần hiển thị phân cấp, hãy sử dụng AndroidView
composable. AndroidView sẽ được truyền một hàm lambda để trả về một
View. AndroidView cũng cung cấp một lệnh gọi lại lệnh update khi lượt xem tăng cao. AndroidView sẽ tái cấu trúc lại bất cứ khi nào một biểu thị State giữa các hàm callback thay đổi. Cũng như nhiều thành phần kết hợp được tích hợp sẵn khác, AndroidView sẽ sử dụng một tham số Modifier để đặt vị trí của nó trong thành phần kết hợp cha, chẳng hạn như vậy.
@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 có tính năng liên kết khung hiển thị
Để nhúng bố cục XML bất kỳ, hãy sử dụng
AndroidViewBinding
do thư viện androidx.compose.ui:ui-viewbinding cung cấp. Để
làm được điều này, dự án của bạn cần bật tính năng liên kết khung hiển thị.
@Composable fun AndroidViewBindingExample() { AndroidViewBinding(ExampleLayoutBinding::inflate) { exampleView.setBackgroundColor(Color.GRAY) } }
AndroidView trong danh sách Lazy
Nếu bạn đang sử dụng AndroidView trong danh sách Lazy (LazyColumn, LazyRow,
Pager, v.v.), hãy cân nhắc sử dụng phương thức nạp chồng AndroidView
được giới thiệu trong phiên bản 1.4.0-rc01. Phương thức nạp chồng này cho phép Compose tái sử dụng thực thể View cơ bản khi thành phần kết hợp chứa được tái sử dụng như trường hợp đối với danh sách Lazy.
Phương thức nạp chồng này của AndroidView bổ sung thêm 2 tham số:
onReset– Lệnh gọi lại được gọi để báo hiệu rằngViewsắp được tái sử dụng. Giá trị này phải khác null để bật tính năng tái sử dụng Khung hiển thị.onRelease(không bắt buộc) – Lệnh gọi lại được gọi để báo hiệu rằngViewđã thoát khỏi thành phần kết hợp và sẽ không được tái sử dụng nữa.
@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() } ) } } }
Các mảnh trong Compose (Bước chuyển tiếp)
Sử dụng thành phần kết hợp AndroidFragment để thêm một Fragment vào Compose.
AndroidFragment có quy trình xử lý dành riêng cho mảnh, chẳng hạn như xoá mảnh khi thành phần kết hợp rời khỏi cấu trúc.
Để gộp thêm một mảnh, hãy sử dụng thành phần kết hợp AndroidFragment. Bạn truyền một lớp Fragment đến AndroidFragment, sau đó lớp này sẽ thêm
một thực thể của lớp đó trực tiếp vào thành phần kết hợp. AndroidFragment cũng cung cấp một đối tượng fragmentState để tạo AndroidFragment với một trạng thái nhất định, arguments để truyền vào mảnh mới và một lệnh gọi lại onUpdate cung cấp mảnh từ thành phần kết hợp. Giống như nhiều thành phần kết hợp được tích hợp sẵn khác, AndroidFragment chấp nhận một tham số Modifier mà bạn có thể sử dụng, chẳng hạn như để đặt vị trí của đối tượng này trong thành phần kết hợp mẹ.
Gọi AndroidFragment trong Compose như sau:
@Composable fun FragmentInComposeExample() { AndroidFragment<MyFragment>() }
Gọi khung Android qua Compose
Compose hoạt động trong các lớp khung Android. Ví dụ: tệp được lưu trữ trên các lớp Khung hiển thị Android (như Activity hoặc Fragment) và có thể sử dụng các lớp khung Android (như Context), tài nguyên hệ thống, Service hoặc BroadcastReceiver.
Để tìm hiểu thêm về tài nguyên hệ thống, hãy xem trang Tài nguyên trong Compose.
Composition Locals (Thành phần kết hợp cục bộ)
Lớp CompositionLocal cho phép truyền dữ liệu trực tiếp thông qua các hàm tổng hợp. Những lớp này thường được cấp một giá trị nào đó ở một nút nhất định trong cây Giao diện người dùng. Giá trị con có thể kết hợp của hàm đó có thể sử dụng giá trị đó mà không cần khai báo lớp CompositionLocal dưới dạng tham số trong hàm có khả năng kết hợp.
Lớp CompositionLocal được dùng để truyền giá trị cho các loại khung Android trong Compose như Context, Configuration hoặc View mà trong đó mã Compose lưu trữ bởi các biến LocalContext, LocalConfiguration, hoặc LocalView tương ứng.
Lưu ý rằng các lớp CompositionLocal có tiền tố Local để chức năng tự động điền trong IDE dễ nhận diện hơn.
Truy cập giá trị hiện tại của CompositionLocal bằng cách sử dụng thuộc tính current. Ví dụ: mã dưới đây sẽ hiển thị một thông báo ngắn bằng cách đưa LocalContext.current vào phương thức 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
Để giới thiệu CompositionLocal và các hiệu ứng, nếu cần đăng ký
BroadcastReceiver từ
một hàm composable, hãy sử dụng LocalContext để sử dụng ngữ cảnh hiện tại và
rememberUpdatedState và DisposableEffect các hiệu ứng phụ.
@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 */ }
Các hoạt động tương tác khác
Nếu không có tiện ích nào được xác định cho các hoạt động tương tác bạn cần thì cách tốt nhất là làm theo hướng dẫn Compose chung, dữ liệu chạy xuống, sự kiện chạy lên (được thảo luận kỹ hơn trong phần Tư duy trong Compose). Ví dụ: thành phần kết hợp này sẽ chạy một hoạt động khác:
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) } }