Sau khi Hoạt động của bạn kiểm soát việc xử lý tất cả phần lồng ghép, bạn có thể dùng các API Compose để xác minh rằng nội dung không bị che khuất và các phần tử có thể tương tác không trùng lặp với giao diện người dùng hệ thống. Các API này cũng đồng bộ hoá bố cục của ứng dụng với các thay đổi về phần lồng ghép.
Xử lý phần lồng ghép bằng cách sử dụng khoảng đệm hoặc công cụ sửa đổi kích thước
Ví dụ: đây là phương thức cơ bản nhất để áp dụng phần lồng ghép cho nội dung của toàn bộ ứng dụng:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() setContent { Box(Modifier.safeDrawingPadding()) { // the rest of the app } } }
Đoạn mã này áp dụng phần lồng ghép cửa sổ safeDrawing làm khoảng đệm xung quanh toàn bộ nội dung của ứng dụng. Mặc dù điều này đảm bảo rằng các phần tử có thể tương tác không trùng lặp với giao diện người dùng hệ thống, nhưng điều này cũng có nghĩa là không có phần nào của ứng dụng sẽ vẽ phía sau giao diện người dùng hệ thống để đạt được hiệu ứng tràn viền. Để tận dụng tối đa toàn bộ cửa sổ, bạn cần tinh chỉnh vị trí áp dụng phần lồng ghép trên cơ sở từng màn hình hoặc từng thành phần.
Tất cả các loại khoảng lùi này đều được tạo ảnh động tự động bằng ảnh động IME được điều chỉnh cho phiên bản cũ về API 21. Do đó, tất cả bố cục của bạn sử dụng các khoảng lùi này cũng sẽ tự động có hiệu ứng khi các giá trị khoảng lùi thay đổi.
Có 3 cách để xử lý phần lồng ghép nhằm điều chỉnh bố cục Thành phần kết hợp:
Đối tượng sửa đổi khoảng đệm
Modifier.windowInsetsPadding(windowInsets: WindowInsets) áp dụng phần lồng ghép cửa sổ đã cho làm khoảng đệm, hoạt động giống như Modifier.padding.
Ví dụ: Modifier.windowInsetsPadding(WindowInsets.safeDrawing) áp dụng phần lồng ghép vẽ an toàn làm khoảng đệm ở cả 4 cạnh.
Ngoài ra, còn có một số phương thức phần mềm tiện ích tích hợp sẵn cho các loại khoảng lùi phổ biến nhất.
Modifier.safeDrawingPadding() là một phương thức như vậy, tương đương với Modifier.windowInsetsPadding(WindowInsets.safeDrawing). Có các đối tượng sửa đổi tương tự cho các loại phần lồng ghép khác.
Đối tượng sửa đổi kích thước phần lồng ghép
Các đối tượng sửa đổi sau đây áp dụng một lượng phần lồng ghép cửa sổ bằng cách đặt kích thước của thành phần thành kích thước của phần lồng ghép:
Áp dụng phía bắt đầu của windowInsets làm chiều rộng (chẳng hạn như |
|
Áp dụng phía cuối của windowInsets làm chiều rộng (chẳng hạn như |
|
Áp dụng cạnh trên của windowInsets làm chiều cao (chẳng hạn như |
|
|
Áp dụng phía dưới cùng của windowInsets làm chiều cao (chẳng hạn như |
Các đối tượng sửa đổi này đặc biệt hữu ích khi định cỡ một Spacer chiếm không gian của phần lồng ghép:
LazyColumn( Modifier.imePadding() ) { // Other content item { Spacer( Modifier.windowInsetsBottomHeight( WindowInsets.systemBars ) ) } }
Mức tiêu thụ nội dung lồng ghép
Các đối tượng sửa đổi khoảng đệm lồng ghép (windowInsetsPadding và các đối tượng hỗ trợ như safeDrawingPadding) sẽ tự động sử dụng phần lồng ghép được áp dụng làm khoảng đệm. Trong khi đi sâu hơn vào cây composition, các modifier khoảng đệm lồng ghép và các modifier kích thước khoảng lùi biết rằng một phần của khoảng lùi đã được các modifier khoảng đệm khoảng lùi bên ngoài tiêu thụ và tránh sử dụng cùng một phần của khoảng lùi nhiều lần, điều này sẽ dẫn đến quá nhiều khoảng trống.
Đối tượng sửa đổi kích thước khoảng lùi cũng tránh sử dụng cùng một phần của khoảng lùi nhiều lần nếu khoảng lùi đã được sử dụng. Tuy nhiên, vì các cửa sổ này thay đổi kích thước trực tiếp nên chúng không sử dụng phần lồng ghép.
Do đó, các đối tượng sửa đổi khoảng đệm lồng nhau sẽ tự động thay đổi lượng khoảng đệm được áp dụng cho từng thành phần kết hợp.
Hãy xem xét ví dụ LazyColumn tương tự như trước, LazyColumn đang được đối tượng sửa đổi imePadding đổi kích thước. Bên trong LazyColumn, mục cuối cùng được định cỡ theo chiều cao của cuối thanh hệ thống:
LazyColumn( Modifier.imePadding() ) { // Other content item { Spacer( Modifier.windowInsetsBottomHeight( WindowInsets.systemBars ) ) } }
Khi IME đóng, imePadding() sẽ không áp dụng khoảng đệm. Do đó, không có phần lồng ghép nào được sử dụng và chiều cao Spacer sẽ khớp với các thanh hệ thống dưới cùng.
Khi IME mở, phần lồng ghép IME sẽ tạo ảnh động để khớp với kích thước của IME và đối tượng sửa đổi imePadding() bắt đầu áp dụng khoảng đệm dưới cùng để đổi kích thước LazyColumn khi IME mở. Khi đối tượng sửa đổi imePadding() bắt đầu áp dụng khoảng đệm dưới cùng, đối tượng này cũng bắt đầu sử dụng lượng phần lồng ghép đó. Do đó, chiều cao của Spacer bắt đầu giảm, vì một phần khoảng cách cho các thanh hệ thống đã được áp dụng bằng đối tượng sửa đổi imePadding(). Sau khi đối tượng sửa đổi imePadding() áp dụng một lượng khoảng đệm dưới lớn hơn thanh hệ thống, chiều cao của Spacer sẽ bằng 0.
Khi IME đóng, các thay đổi sẽ diễn ra theo chiều ngược lại: Spacer mở rộng từ chiều cao bằng 0 khi imePadding() áp dụng ít hơn các thanh hệ thống dưới cùng.
Cuối cùng, chiều cao Spacer sẽ khớp với các thanh hệ thống sau khi IME hoàn tất quá trình chuyển động ra ngoài.
TextField.Hành vi này được thực hiện thông qua hoạt động giao tiếp giữa tất cả các đối tượng sửa đổi windowInsetsPadding và có thể chịu ảnh hưởng theo một số cách khác.
Modifier.consumeWindowInsets(insets: WindowInsets) cũng sử dụng phần lồng ghép theo cách tương tự như Modifier.windowInsetsPadding, nhưng không áp dụng phần lồng ghép đã sử dụng làm khoảng đệm. Điều này sẽ hữu ích khi kết hợp với các đối tượng sửa đổi kích thước khoảng lùi, để cho biết với các thành phần đồng cấp rằng một số lượng nhất định các khoảng lùi đã được tiêu thụ:
Column(Modifier.verticalScroll(rememberScrollState())) { Spacer(Modifier.windowInsetsTopHeight(WindowInsets.systemBars)) Column( Modifier.consumeWindowInsets( WindowInsets.systemBars.only(WindowInsetsSides.Vertical) ) ) { // content Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.ime)) } Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.systemBars)) }
Modifier.consumeWindowInsets(paddingValues: PaddingValues) hoạt động rất giống với phiên bản có đối số WindowInsets, nhưng lấy một PaddingValues tuỳ ý để sử dụng. Điều này hữu ích khi thông báo cho các thành phần con khi khoảng đệm hoặc khoảng cách được cung cấp bằng một cơ chế khác ngoài các đối tượng sửa đổi khoảng đệm lồng ghép, chẳng hạn như một Modifier.padding thông thường hoặc các thành phần giãn cách có chiều cao cố định:
Column(Modifier.padding(16.dp).consumeWindowInsets(PaddingValues(16.dp))) { // content Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.ime)) }
Trong trường hợp cần các phần lồng ghép cửa sổ thô mà không cần sử dụng, hãy dùng trực tiếp các giá trị WindowInsets hoặc dùng WindowInsets.asPaddingValues() để trả về PaddingValues của các phần lồng ghép không bị ảnh hưởng bởi mức tiêu thụ.
Tuy nhiên, do những lưu ý sau, hãy ưu tiên sử dụng đối tượng sửa đổi khoảng đệm phần lồng ghép cửa sổ và đối tượng sửa đổi kích thước phần lồng ghép cửa sổ bất cứ khi nào có thể.
Phần lồng ghép và các giai đoạn Jetpack Compose
Compose sử dụng các API cốt lõi AndroidX cơ bản để cập nhật và tạo hiệu ứng động cho phần lồng ghép, sử dụng các API nền tảng cơ bản để quản lý phần lồng ghép. Do hành vi của nền tảng đó, phần lồng ghép có mối quan hệ đặc biệt với các giai đoạn của Jetpack Compose.
Giá trị của phần lồng ghép được cập nhật sau giai đoạn thành phần, nhưng trước giai đoạn bố cục. Điều này có nghĩa là việc đọc giá trị của phần lồng ghép trong thành phần thường sử dụng giá trị của phần lồng ghép muộn một khung hình. Các đối tượng sửa đổi tích hợp được mô tả trên trang này được tạo để trì hoãn việc sử dụng các giá trị của khoảng lùi cho đến giai đoạn bố cục, điều này đảm bảo rằng các giá trị khoảng lùi được dùng trên cùng một khung hình khi chúng được cập nhật.