Phản ứng để tập trung
Sử dụng bộ sưu tập để sắp xếp ngăn nắp các trang
Lưu và phân loại nội dung dựa trên lựa chọn ưu tiên của bạn.
Cung cấp chỉ dẫn bằng hình ảnh để dễ dàng lấy tiêu điểm hơn
Mặc dù tất cả phần tử có thể làm tâm điểm trong Giao diện Material đều đã có kiểu tiêu điểm
phù hợp với chủ đề, bạn có thể cần thêm một số
phần tử hình ảnh để làm cho
dễ nhận ra hơn. Một giải pháp hay là thay đổi đường viền của
phần tử có màu có độ tương phản tốt với nền:
var color by remember { mutableStateOf(Color.White) }
Card(
modifier = Modifier
.onFocusChanged {
color = if (it.isFocused) Red else White
}
.border(5.dp, color)
) {}
Trong ví dụ này, remember
được dùng để lưu trữ màu của đường viền trên
kết hợp lại và đường viền của phần tử được cập nhật mỗi lần phần tử
tăng hoặc mất tiêu điểm.
Triển khai chỉ dẫn bằng hình ảnh nâng cao
Với Jetpack Compose, bạn cũng có thể tạo hình ảnh tinh vi và nâng cao hơn
phù hợp hơn với giao diện người dùng.
- Trước tiên, hãy tạo một
IndicationInstance
để vẽ tín hiệu bạn muốn trong giao diện người dùng một cách trực quan:
private class MyHighlightIndicationNode(private val interactionSource: InteractionSource) :
Modifier.Node(), DrawModifierNode {
private var isFocused = false
override fun onAttach() {
coroutineScope.launch {
var focusCount = 0
interactionSource.interactions.collect { interaction ->
when (interaction) {
is FocusInteraction.Focus -> focusCount++
is FocusInteraction.Unfocus -> focusCount--
}
val focused = focusCount > 0
if (isFocused != focused) {
isFocused = focused
invalidateDraw()
}
}
}
}
override fun ContentDrawScope.draw() {
drawContent()
if (isFocused) {
drawRect(size = size, color = Color.White, alpha = 0.2f)
}
}
}
- Tiếp theo, hãy tạo một
Indication
và ghi nhớ trạng thái làm tiêu điểm:
object MyHighlightIndication : IndicationNodeFactory {
override fun create(interactionSource: InteractionSource): DelegatableNode {
return MyHighlightIndicationNode(interactionSource)
}
override fun hashCode(): Int = -1
override fun equals(other: Any?) = other === this
}
- Thêm cả
Indication
và InteractionSource
vào giao diện người dùng thông qua đối tượng sửa đổi indication()
:
var interactionSource = remember { MutableInteractionSource() }
Card(
modifier = Modifier
.clickable(
interactionSource = interactionSource,
indication = MyHighlightIndication,
enabled = true,
onClick = { }
)
) {
Text("hello")
}
Hiểu rõ trạng thái của tiêu điểm
Thông thường, mỗi khi một trạng thái của tiêu điểm thay đổi, FocusEvent
sẽ được kích hoạt
cây này và thành phần mẹ của đối tượng sửa đổi focusable()
có thể theo dõi nó bằng cách sử dụng
Đối tượng sửa đổi onFocusChanged()
.
Nếu cần biết trạng thái của tiêu điểm,bạn có thể sử dụng kết hợp các API này
bằng đối tượng sửa đổi onFocusChanged
:
isFocused
trả về true
nếu thành phần kết hợp đính kèm đối tượng sửa đổi
được lấy tiêu điểm
hasFocus
hoạt động tương tự như isFocused
, nhưng có một điểm khác biệt đáng kể:
thay vì chỉ kiểm tra hiện tại, nó sẽ kiểm tra xem phần tử hoặc một trong các
trẻ em được tập trung
isCaptured
sẽ trả về true
bất cứ khi nào tiêu điểm được giữ. Điều này xảy ra, đối với
khi TextField
chứa dữ liệu không chính xác để cố gắng tập trung
các yếu tố khác sẽ không xoá tiêu điểm.
Các trường này được hiển thị dưới đây:
Modifier.onFocusChanged {
val isFocused = it.isFocused
val hasFocus = it.hasFocus
val isCaptured= it.isCaptured
}
Đề xuất cho bạn
Nội dung và mã mẫu trên trang này phải tuân thủ các giấy phép như mô tả trong phần Giấy phép nội dung. Java và OpenJDK là nhãn hiệu hoặc nhãn hiệu đã đăng ký của Oracle và/hoặc đơn vị liên kết của Oracle.
Cập nhật lần gần đây nhất: 2025-08-27 UTC.
[[["Dễ hiểu","easyToUnderstand","thumb-up"],["Giúp tôi giải quyết được vấn đề","solvedMyProblem","thumb-up"],["Khác","otherUp","thumb-up"]],[["Thiếu thông tin tôi cần","missingTheInformationINeed","thumb-down"],["Quá phức tạp/quá nhiều bước","tooComplicatedTooManySteps","thumb-down"],["Đã lỗi thời","outOfDate","thumb-down"],["Vấn đề về bản dịch","translationIssue","thumb-down"],["Vấn đề về mẫu/mã","samplesCodeIssue","thumb-down"],["Khác","otherDown","thumb-down"]],["Cập nhật lần gần đây nhất: 2025-08-27 UTC."],[],[],null,["# React to focus\n\nProvide visual cues for easier focus visualization\n--------------------------------------------------\n\nWhile all the focusable elements from Material Theme already have a focus style\nthat matches the theme, you might need to add some visual elements to make the\nfocused element easier to spot. A good solution would be to change the border of\nyour element with a color that has a good contrast with the background:\n\n\n```kotlin\nvar color by remember { mutableStateOf(Color.White) }\nCard(\n modifier = Modifier\n .onFocusChanged {\n color = if (it.isFocused) Red else White\n }\n .border(5.dp, color)\n) {}https://github.com/android/snippets/blob/dd30aee903e8c247786c064faab1a9ca8d10b46e/compose/snippets/src/main/java/com/example/compose/snippets/touchinput/focus/FocusSnippets.kt#L427-L434\n```\n\n\u003cbr /\u003e\n\nIn this example, `remember` is used to store the color of the border across\nrecompositions, and the outline of the element is updated every time the element\ngains or loses focus.\n\n### Implement advanced visual cues\n\nWith Jetpack Compose, you can also create more sophisticated and advanced visual\ncues that match better with your UI.\n\n1. First, create an `IndicationInstance` that visually draws the cue you want in your UI: \n\n ```kotlin\n private class MyHighlightIndicationNode(private val interactionSource: InteractionSource) :\n Modifier.Node(), DrawModifierNode {\n private var isFocused = false\n\n override fun onAttach() {\n coroutineScope.launch {\n var focusCount = 0\n interactionSource.interactions.collect { interaction -\u003e\n when (interaction) {\n is FocusInteraction.Focus -\u003e focusCount++\n is FocusInteraction.Unfocus -\u003e focusCount--\n }\n val focused = focusCount \u003e 0\n if (isFocused != focused) {\n isFocused = focused\n invalidateDraw()\n }\n }\n }\n }\n\n override fun ContentDrawScope.draw() {\n drawContent()\n if (isFocused) {\n drawRect(size = size, color = Color.White, alpha = 0.2f)\n }\n }\n }\n https://github.com/android/snippets/blob/dd30aee903e8c247786c064faab1a9ca8d10b46e/compose/snippets/src/main/java/com/example/compose/snippets/touchinput/focus/FocusSnippets.kt#L439-L467\n ```\n2. Next, create an `Indication` and remember the focused state: \n\n ```kotlin\n object MyHighlightIndication : IndicationNodeFactory {\n override fun create(interactionSource: InteractionSource): DelegatableNode {\n return MyHighlightIndicationNode(interactionSource)\n }\n\n override fun hashCode(): Int = -1\n\n override fun equals(other: Any?) = other === this\n }https://github.com/android/snippets/blob/dd30aee903e8c247786c064faab1a9ca8d10b46e/compose/snippets/src/main/java/com/example/compose/snippets/touchinput/focus/FocusSnippets.kt#L471-L479\n ```\n3. Add both the `Indication` and an `InteractionSource` to the UI, via the `indication()` modifier: \n\n ```kotlin\n var interactionSource = remember { MutableInteractionSource() }\n\n Card(\n modifier = Modifier\n .clickable(\n interactionSource = interactionSource,\n indication = MyHighlightIndication,\n enabled = true,\n onClick = { }\n )\n ) {\n Text(\"hello\")\n }https://github.com/android/snippets/blob/dd30aee903e8c247786c064faab1a9ca8d10b46e/compose/snippets/src/main/java/com/example/compose/snippets/touchinput/focus/FocusSnippets.kt#L485-L497\n ```\n\nUnderstand the state of the focus\n---------------------------------\n\nGenerally, every time a state of the focus changes, a `FocusEvent` is fired up\nthe tree, and the parents of a `focusable()` modifier can listen to it using the\n`onFocusChanged()` modifier.\n\nIf you need to know the state of the focus,you can use these APIs in conjunction\nwith the `onFocusChanged` modifier:\n\n- `isFocused` returns `true` if the composable to which the modifier is attached is focused\n- `hasFocus` works similarly to `isFocused`, but with a substantial difference: rather than checking only the current, it checks if the element or one of its children is focused\n- `isCaptured` returns `true` whenever the focus is held. This happens, for instance, when a `TextField` contains incorrect data, so that trying to focus other elements will not clear the focus.\n\nThese fields are shown below: \n\n Modifier.onFocusChanged {\n val isFocused = it.isFocused\n val hasFocus = it.hasFocus\n val isCaptured= it.isCaptured\n }\n\nRecommended for you\n-------------------\n\n- Note: link text is displayed when JavaScript is off\n- [Change focus behavior](/develop/ui/compose/touch-input/focus/change-focus-behavior)\n- [Material Design 2 in Compose](/develop/ui/compose/designsystems/material)\n- [Handle user input](/develop/ui/compose/text/user-input)"]]