Theo mặc định, Material, giao diện người dùng Compose và API Foundation triển khai và cung cấp nhiều phương pháp hỗ trợ tiếp cận. Các thành phần này chứa ngữ nghĩa tích hợp theo vai trò và chức năng cụ thể, nghĩa là hầu hết các tính năng hỗ trợ tiếp cận đều được cung cấp mà không cần thêm hoặc ít phải làm gì thêm.
Việc sử dụng API thích hợp cho mục đích thích hợp thường có nghĩa là các thành phần đi kèm với các hành vi hỗ trợ tiếp cận được xác định trước bao gồm các trường hợp sử dụng tiêu chuẩn, nhưng hãy nhớ kiểm tra kỹ xem các chế độ mặc định này có phù hợp với nhu cầu hỗ trợ tiếp cận của bạn hay không. Nếu không, Compose cũng cung cấp các cách để đáp ứng các yêu cầu cụ thể hơn.
Việc nắm được ngữ nghĩa và mẫu hỗ trợ tiếp cận mặc định trong API Compose giúp bạn hiểu cách sử dụng các API đó theo hướng hỗ trợ tiếp cận, cũng như hỗ trợ tiếp cận trong nhiều thành phần tuỳ chỉnh hơn.
Kích thước tối thiểu của đích chạm
Mọi phần tử trên màn hình mà ai đó có thể nhấp, chạm vào hoặc tương tác đều phải đủ lớn để tương tác đáng tin cậy. Khi xác định kích thước các phần tử này, hãy đảm bảo đặt kích thước tối thiểu là 48dp để tuân thủ đúng nguyên tắc hỗ trợ tiếp cận của Material Design.
Các thành phần Material, chẳng hạn như Checkbox
, RadioButton
, Switch
, Slider
và Surface
— đặt kích thước tối thiểu này nội bộ, nhưng chỉ khi thành phần có thể nhận được thao tác của người dùng. Ví dụ: khi tham số onCheckedChange
của Checkbox
được đặt giá trị rỗng, thì hộp đánh dấu sẽ bao gồm khoảng đệm để có chiều rộng và chiều cao ít nhất là 48 dp.
@Composable private fun CheckableCheckbox() { Checkbox(checked = true, onCheckedChange = {}) }

Khi tham số onCheckedChange
được đặt thành rỗng, khoảng đệm không được thêm vào vì không thể tương tác trực tiếp với thành phần này.
@Composable private fun NonClickableCheckbox() { Checkbox(checked = true, onCheckedChange = null) }

Khi triển khai các chế độ điều khiển lựa chọn như Switch
, RadioButton
hoặc Checkbox
, bạn thường nâng hành vi có thể nhấp lên vùng chứa mẹ bằng cách đặt lệnh gọi lại lượt nhấp trên thành phần kết hợp thành null
rồi thêm một đối tượng sửa đổi toggleable
hoặc selectable
cho thành phần kết hợp mẹ.
@Composable private fun CheckableRow() { MaterialTheme { var checked by remember { mutableStateOf(false) } Row( Modifier .toggleable( value = checked, role = Role.Checkbox, onValueChange = { checked = !checked } ) .padding(16.dp) .fillMaxWidth() ) { Text("Option", Modifier.weight(1f)) Checkbox(checked = checked, onCheckedChange = null) } } }

Khi kích thước của một thành phần kết hợp có thể nhấp nhỏ hơn kích thước đích chạm tối thiểu, Compose vẫn tăng kích thước đích chạm. Compose làm như vậy bằng cách mở rộng kích thước đích chạm nằm ngoài phạm vi của thành phần có thể kết hợp.
Ví dụ sau đây chứa một Box
rất nhỏ có thể nhấp. Khu vực đích chạm tự động mở rộng ra ngoài phạm vi của Box
, vì vậy, thao tác nhấn vào bên cạnh Box
sẽ vẫn kích hoạt sự kiện nhấp.
@Composable private fun SmallBox() { var clicked by remember { mutableStateOf(false) } Box( Modifier .size(100.dp) .background(if (clicked) Color.DarkGray else Color.LightGray) ) { Box( Modifier .align(Alignment.Center) .clickable { clicked = !clicked } .background(Color.Black) .size(1.dp) ) } }

Để ngăn chặn sự trùng lặp có thể xảy ra giữa các khu vực cảm ứng của các thành phần kết hợp, hãy luôn sử dụng kích thước tối thiểu đủ lớn cho thành phần kết hợp. Trong ví dụ này, điều đó có nghĩa là sử dụng đối tượng sửa đổi sizeIn
để đặt kích thước tối thiểu cho hộp bên trong:
@Composable private fun LargeBox() { var clicked by remember { mutableStateOf(false) } Box( Modifier .size(100.dp) .background(if (clicked) Color.DarkGray else Color.LightGray) ) { Box( Modifier .align(Alignment.Center) .clickable { clicked = !clicked } .background(Color.Black) .sizeIn(minWidth = 48.dp, minHeight = 48.dp) ) } }

Phần tử đồ hoạ
Khi bạn xác định thành phần kết hợp Image
hoặc Icon
, không có cách tự động nào để khung Android hiểu nội dung mà ứng dụng đang hiển thị. Bạn cần truyền nội dung mô tả dạng văn bản của phần tử đồ hoạ.
Hãy tưởng tượng một màn hình mà người dùng có thể chia sẻ trang hiện tại với bạn bè. Màn hình này chứa biểu tượng chia sẻ có thể nhấp:

Chỉ dựa vào biểu tượng này, khung Android sẽ không thể mô tả cho người dùng khiếm thị. Khung Android cần có thêm mô tả bằng văn bản của biểu tượng đó.
Tham số contentDescription
mô tả một phần tử đồ hoạ. Sử dụng chuỗi đã được bản địa hoá vì người dùng sẽ nhìn thấy chuỗi này.
@Composable private fun ShareButton(onClick: () -> Unit) { IconButton(onClick = onClick) { Icon( imageVector = Icons.Filled.Share, contentDescription = stringResource(R.string.label_share) ) } }
Một số thành phần đồ hoạ chỉ mang tính chất trang trí và bạn có thể không muốn thông báo cho người dùng. Khi đặt tham số contentDescription
thành null
, bạn chỉ báo cho khung Android rằng phần tử này không có hành động hoặc trạng thái liên kết.
@Composable private fun PostImage(post: Post, modifier: Modifier = Modifier) { val image = post.imageThumb ?: painterResource(R.drawable.placeholder_1_1) Image( painter = image, // Specify that this image has no semantic meaning contentDescription = null, modifier = modifier .size(40.dp, 40.dp) .clip(MaterialTheme.shapes.small) ) }
contentDescription
chủ yếu được dùng cho các phần tử đồ hoạ, chẳng hạn như hình ảnh. Các thành phần Material, chẳng hạn như Button
hoặc Text
và các hành vi có thể thao tác, chẳng hạn như clickable
hoặc toggleable
, đi kèm với các ngữ nghĩa được xác định trước khác mô tả hành vi nội tại của chúng và có thể được thay đổi thông qua các API Compose khác.
Yếu tố tương tác
API Material và Foundation Compose tạo các thành phần trên giao diện người dùng mà người dùng có thể tương tác thông qua các API đối tượng sửa đổi clickable
và toggleable
. Vì các thành phần có thể tương tác có thể bao gồm nhiều phần tử, nên theo mặc định, clickable
và toggleable
sẽ hợp nhất ngữ nghĩa của các phần tử con để thành phần được coi là một thực thể logic.
Ví dụ: Button
Material có thể bao gồm một biểu tượng con và một số văn bản.
Thay vì coi các thành phần con là các thành phần riêng lẻ, theo mặc định, Nút Material sẽ hợp nhất ngữ nghĩa của các thành phần con để các dịch vụ hỗ trợ tiếp cận có thể nhóm các thành phần đó theo cách thích hợp:

Tương tự, việc sử dụng đối tượng sửa đổi clickable
cũng khiến một thành phần kết hợp hợp nhất ngữ nghĩa của các thành phần con thành một thực thể duy nhất. Thực thể này được gửi đến các dịch vụ hỗ trợ tiếp cận bằng cách thể hiện hành động tương ứng:
Row( // Uses `mergeDescendants = true` under the hood modifier = Modifier.clickable { openArticle() } ) { Icon( painter = painterResource(R.drawable.ic_logo), contentDescription = "Open", ) Text("Accessibility in Compose") }
Bạn cũng có thể đặt một onClickLabel
cụ thể trên thành phần mẹ có thể nhấp để cung cấp thêm thông tin cho các dịch vụ hỗ trợ tiếp cận và cung cấp nội dung trình bày hành động tinh tế hơn:
Row( modifier = Modifier .clickable(onClickLabel = "Open this article") { openArticle() } ) { Icon( painter = painterResource(R.drawable.ic_logo), contentDescription = "Open" ) Text("Accessibility in Compose") }
Lấy TalkBack làm ví dụ, đối tượng sửa đổi clickable
này và nhãn lượt nhấp của đối tượng đó sẽ cho phép TalkBack cung cấp gợi ý hành động "Nhấn đúp để mở bài viết này", thay vì phản hồi mặc định chung hơn là "Nhấn đúp để kích hoạt".
Nội dung phản hồi này thay đổi tuỳ thuộc vào loại hành động. Thao tác nhấn và giữ sẽ cung cấp gợi ý TalkBack là "Nhấn đúp và giữ để", theo sau là một nhãn:
Row( modifier = Modifier .combinedClickable( onLongClickLabel = "Bookmark this article", onLongClick = { addToBookmarks() }, onClickLabel = "Open this article", onClick = { openArticle() }, ) ) {}
Trong một số trường hợp, bạn có thể không có quyền truy cập trực tiếp vào đối tượng sửa đổi clickable
(ví dụ: khi đối tượng này được đặt ở một vị trí nào đó trong lớp lồng nhau thấp hơn), nhưng vẫn muốn thay đổi nhãn thông báo từ mặc định. Để thực hiện việc này, hãy tách việc đặt clickable
khỏi việc sửa đổi thông báo bằng cách sử dụng đối tượng sửa đổi semantics
và đặt nhãn lượt nhấp ở đó để sửa đổi nội dung thể hiện hành động:
@Composable private fun ArticleList(openArticle: () -> Unit) { NestedArticleListItem( // Clickable is set separately, in a nested layer: onClickAction = openArticle, // Semantics are set here: modifier = Modifier.semantics { onClick( label = "Open this article", action = { // Not needed here: openArticle() true } ) } ) }
Trong trường hợp này, bạn không cần truyền thao tác nhấp hai lần, vì các API Compose hiện có, chẳng hạn như clickable
hoặc Button
, sẽ xử lý thao tác này cho bạn. Điều này là do logic hợp nhất đảm bảo rằng nhãn và thao tác sửa đổi ngoài cùng được lấy cho thông tin hiện có.
Trong ví dụ trước, thao tác nhấp openArticle()
được NestedArticleListItem
tự động truyền sâu xuống ngữ nghĩa clickable
và có thể được để trống trong thao tác đối tượng sửa đổi ngữ nghĩa thứ hai. Tuy nhiên, nhãn lượt nhấp được lấy từ đối tượng sửa đổi ngữ nghĩa thứ hai onClick(label = "Open this article")
, vì nhãn này không có trong đối tượng sửa đổi ngữ nghĩa đầu tiên.
Bạn có thể gặp phải các trường hợp mà bạn muốn ngữ nghĩa của phần tử con được hợp nhất vào phần tử mẹ, nhưng điều đó không xảy ra. Hãy xem phần Hợp nhất và xoá để biết thêm thông tin chi tiết.
Thành phần tuỳ chỉnh
Đối với các thành phần tuỳ chỉnh, theo quy tắc chung, hãy xem cách triển khai một thành phần tương tự trong thư viện Material hoặc các thư viện Compose khác, đồng thời bắt chước hoặc sửa đổi hành vi hỗ trợ tiếp cận của thành phần đó khi cần thiết.
Ví dụ: nếu bạn đang thay thế Checkbox
trong Material bằng phương thức triển khai của riêng mình, thì việc xem phương thức triển khai Hộp đánh dấu hiện có sẽ nhắc bạn thêm đối tượng sửa đổi triStateToggleable
. Đối tượng này sẽ xử lý các thuộc tính hỗ trợ tiếp cận cho thành phần này.
Ngoài ra, hãy tận dụng nhiều thành phần sửa đổi Foundation, vì các thành phần sửa đổi này bao gồm các tính năng hỗ trợ tiếp cận ngay từ đầu, cũng như các phương pháp Compose hiện có được đề cập trong phần này.
Bạn cũng có thể tìm thấy ví dụ về thành phần nút bật/tắt tuỳ chỉnh trong phần Xoá và đặt ngữ nghĩa, cũng như thông tin chi tiết hơn về cách hỗ trợ chức năng hỗ trợ tiếp cận trong các thành phần tuỳ chỉnh trong nguyên tắc về API.
Đề xuất cho bạn
- Lưu ý: văn bản có đường liên kết sẽ hiện khi JavaScript tắt
- Hỗ trợ tiếp cận trong Compose
- [Material Design 2 trong Compose][19]
- Kiểm thử bố cục Compose