Bạn có thể đưa một hệ thống phân cấp thành phần hiển thị 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ế.
Để thêm một phần tử hoặc hệ phân cấp khung hiển thị, hãy sử dụng thành phần kết hợp AndroidView
. AndroidView
sẽ được truyền một hàm lambda để trả về một lớp 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 { 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
có liên kết khung hiển thị
Để nhúng bố cục XML bất kỳ, hãy sử dụng API 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 sử dụng lại thực thể View
cơ bản khi thành phần chứa được sử dụng lại như trường hợp của danh sách Lazy.
Phương thức nạp chồng AndroidView
này thêm 2 tham số bổ sung:
onReset
– Lệnh gọi lại được gọi để báo hiệu rằngView
sắp được sử dụng lại. Giá trị này không được rỗng để cho phép sử dụng lại Chế độ xem.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 và sẽ không được sử dụng lại.
@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() } ) } } }
Các mảnh trong Compose
Sử dụng thành phần kết hợp AndroidViewBinding
để thêm một Fragment
vào Compose.
AndroidViewBinding
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.
Hãy làm việc này bằng cách tăng cường tệp XML chứa FragmentContainerView
dưới dạng chủ sở hữu của Fragment
.
Chẳng hạn nếu đã xác định được my_fragment_layout.xml
, bạn có thể sử dụng mã như thế này trong khi thay thế thuộc tính XML android:name
bằng tên lớp Fragment
của bạn:
<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" />
Tăng cường mảnh này trong Compose như sau:
@Composable fun FragmentInComposeExample() { AndroidViewBinding(MyFragmentLayoutBinding::inflate) { val myFragment = fragmentContainerView.getFragment<MyFragment>() // ... } }
Nếu cần sử dụng nhiều mảnh trong cùng một bố cục, hãy đảm bảo là bạn đã xác định một mã nhận dạng duy nhất cho mỗi FragmentContainerView
.
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") } }
Để có ví dụ hoàn chỉnh hơn, hãy xem thêm mục Nghiên cứu điển hình: BroadcastReceivers ở cuối tài liệu này.
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) } }
Nghiên cứu điển hình: Broadcast receiver
Để có một ví dụ thực tế hơn về các tính năng mà bạn muốn di chuyển hoặc triển khai trong Compose và để hiển thị CompositionLocal
cùng các hiệu ứng phụ, hãy giả sử BroadcastReceiver
cần được đăng ký qua một hàm có khả năng kết hợp.
Giải pháp này tận dụng LocalContext
để sử dụng ngữ cảnh hiện tại, cũng như rememberUpdatedState
và các hiệu ứng phụ 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 */ }
Bước tiếp theo
Giờ đây, bạn đã biết các API có khả năng tương tác khi sử dụng Compose trong Khung hiển thị và ngược lại, hãy khám phá trang Những điểm cần cân nhắc khác để tìm hiểu thêm.
Đề xuất cho bạn
- Lưu ý: văn bản có đường liên kết sẽ hiện khi JavaScript tắt
- Những điểm khác cần cân nhắc
- Những hiệu ứng phụ trong ứng dụng Compose
- Dữ liệu trong phạm vi cục bộ với CompositionLocal