Khi tôi viết bài viết cuối cùng về Jetpack Compose, tôi đã nói rằng Jetpack Compose thiếu một số thành phần cơ bản (theo ý kiến của tôi) và một trong số đó là chú giải công cụ.
Vào thời điểm đó, không có thành phần kết hợp tích hợp sẵn để hiển thị chú giải công cụ và có một số giải pháp thay thế được đăng tải trực tuyến. Vấn đề với những giải pháp đó là khi Jetpack Compose phát hành phiên bản mới hơn, những giải pháp đó có thể bị hỏng. Vì vậy, điều đó không lý tưởng chút nào và cộng đồng đã hy vọng rằng một lúc nào đó trong tương lai, các chú giải công cụ sẽ được bổ sung thêm hỗ trợ.
Tôi rất vui khi thông báo rằng kể từ phiên bản 1.1.0 của Compose Material 3, chúng tôi hiện đã tích hợp sẵn tính năng hỗ trợ chú giải công cụ. 👏
Mặc dù bản thân điều này đã tuyệt vời nhưng đã hơn một năm trôi qua kể từ khi phiên bản đó được phát hành. Và với các phiên bản tiếp theo, API liên quan đến chú giải công cụ cũng thay đổi đáng kể.
Nếu xem qua nhật ký thay đổi, bạn sẽ thấy API công khai và API nội bộ đã thay đổi như thế nào. Vì vậy, hãy nhớ rằng khi bạn đọc bài viết này, mọi thứ có thể đã tiếp tục thay đổi vì mọi thứ liên quan đến Chú giải công cụ vẫn được đánh dấu bằng chú thích ExperimentalMaterial3Api::class .
❗️ Phiên bản tài liệu 3 được sử dụng cho bài viết này là 1.2.1, được phát hành vào ngày 6 tháng 3 năm 2024
Hiện chúng tôi hỗ trợ hai loại chú giải công cụ khác nhau:
-
Chú giải công cụ đơn giản
-
Chú giải công cụ đa phương tiện
Chú giải công cụ đơn giản
Bạn có thể sử dụng loại đầu tiên để cung cấp thông tin về nút biểu tượng mà nếu không thì sẽ không rõ ràng. Ví dụ:bạn có thể sử dụng chú giải công cụ đơn giản để cho người dùng biết nút biểu tượng đại diện cho điều gì.

Để thêm chú giải công cụ vào ứng dụng của bạn, bạn sử dụng TooltipBox có thể kết hợp được. Thành phần kết hợp này có một số đối số:
fun TooltipBox(
positionProvider: PopupPositionProvider,
tooltip: @Composable TooltipScope.() -> Unit,
state: TooltipState,
modifier: Modifier = Modifier,
focusable: Boolean = true,
enableUserInput: Boolean = true,
content: @Composable () -> Unit,
)
Một số trong số này chắc hẳn đã quen thuộc với bạn nếu bạn đã từng sử dụng Thành phần kết hợp trước đây. Tôi sẽ nêu bật những cái có trường hợp sử dụng cụ thể ở đây:
-
locationProvider - Của PopupPositionProvider gõ và được sử dụng để tính toán vị trí của chú giải công cụ.
-
chú giải công cụ - Đây là nơi bạn có thể thiết kế giao diện người dùng cho biết chú giải công cụ sẽ trông như thế nào.
-
trạng thái - Điều này giữ trạng thái được liên kết với một phiên bản Chú giải công cụ cụ thể. Nó hiển thị các phương thức như hiển thị/loại bỏ chú giải công cụ và khi khởi tạo một phiên bản của một chú giải công cụ, bạn có thể khai báo xem chú giải công cụ có nên tồn tại lâu dài hay không (nghĩa là liệu nó có tiếp tục hiển thị trên màn hình cho đến khi người dùng thực hiện hành động nhấp chuột bên ngoài chú giải công cụ hay không).
-
nội dung - Đây là giao diện người dùng mà chú giải công cụ sẽ hiển thị bên trên/bên dưới.
Dưới đây là ví dụ về việc khởi tạo BasicTooltipBox với tất cả các đối số có liên quan được điền vào:
@OptIn(ExperimentalFoundationApi::class, ExperimentalMaterial3Api::class)
@Composable
fun BasicTooltip() {
val tooltipPosition = TooltipDefaults.rememberPlainTooltipPositionProvider()
val tooltipState = rememberBasicTooltipState(isPersistent = false)
BasicTooltipBox(positionProvider = tooltipPosition,
tooltip = { Text("Hello World") } ,
state = tooltipState) {
IconButton(onClick = { }) {
Icon(imageVector = Icons.Filled.Favorite,
contentDescription = "Your icon's description")
}
}
}

Jetpack Compose có một lớp tích hợp có tên là TooltipDefaults. Bạn có thể sử dụng lớp này để giúp bạn khởi tạo các đối số tạo nên TooltipBox. Ví dụ:bạn có thể sử dụng TooltipDefaults.rememberPlainTooltipPositionProvider để định vị chính xác chú giải công cụ liên quan đến phần tử neo.
Chú giải công cụ phong phú
Chú giải công cụ đa phương tiện chiếm nhiều không gian hơn chú giải công cụ đơn giản và có thể được sử dụng để cung cấp thêm ngữ cảnh về chức năng của nút biểu tượng. Khi chú giải công cụ được hiển thị, bạn có thể thêm các nút và liên kết vào đó để cung cấp thêm giải thích hoặc định nghĩa.
Nó được khởi tạo theo cách tương tự như một chú giải công cụ đơn giản, bên trong TooltipBox, nhưng bạn sử dụng thành phần kết hợp RichTooltip.
TooltipBox(positionProvider = tooltipPosition,
tooltip = {
RichTooltip(
title = { Text("RichTooltip") },
caretSize = caretSize,
action = {
TextButton(onClick = {
scope.launch {
tooltipState.dismiss()
tooltipState.onDispose()
}
}) {
Text("Dismiss")
}
}
) {
Text("This is where a description would go.")
}
},
state = tooltipState) {
IconButton(onClick = {
/* Icon button's click event */
}) {
Icon(imageVector = tooltipIcon,
contentDescription = "Your icon's description",
tint = iconColor)
}
}
Một số điều cần lưu ý về chú giải công cụ Rich:
-
Chú giải công cụ phong phú có hỗ trợ dấu mũ.
-
Bạn có thể thêm một hành động (tức là một nút) vào chú giải công cụ để cung cấp cho người dùng tùy chọn tìm hiểu thêm thông tin.
-
Bạn có thể thêm logic để loại bỏ chú giải công cụ.


Vỏ viền
Khi bạn chọn đánh dấu trạng thái chú giải công cụ của mình là liên tục , điều đó có nghĩa là khi người dùng tương tác với giao diện người dùng hiển thị chú giải công cụ của bạn, nó sẽ vẫn hiển thị cho đến khi người dùng nhấn vào bất kỳ vị trí nào khác trên màn hình.
Nếu bạn xem ví dụ về chú giải công cụ Rich ở trên, bạn có thể nhận thấy rằng chúng tôi đã thêm nút để loại bỏ chú giải công cụ sau khi nó được nhấp vào.
Có một vấn đề xảy ra khi người dùng nhấn nút đó. Vì hành động loại bỏ được thực hiện trên chú giải công cụ nên nếu người dùng muốn thực hiện một lần nhấn và giữ khác trên mục UI gọi ra chú giải công cụ này thì chú giải công cụ sẽ không được hiển thị lại. Điều này có nghĩa là trạng thái của chú giải công cụ liên tục bị loại bỏ. Vậy chúng ta phải làm cách nào để giải quyết vấn đề này?

Để “đặt lại” trạng thái của chú giải công cụ, chúng ta phải gọi onDispose phương thức được hiển thị thông qua trạng thái chú giải công cụ. Sau khi chúng tôi thực hiện điều đó, trạng thái chú giải công cụ sẽ được đặt lại và chú giải công cụ sẽ được hiển thị lại khi người dùng nhấn và giữ mục UI.
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun RichTooltip() {
val tooltipPosition = TooltipDefaults.rememberRichTooltipPositionProvider()
val tooltipState = rememberTooltipState(isPersistent = true)
val scope = rememberCoroutineScope()
TooltipBox(positionProvider = tooltipPosition,
tooltip = {
RichTooltip(
title = { Text("RichTooltip") },
caretSize = TooltipDefaults.caretSize,
action = {
TextButton(onClick = {
scope.launch {
tooltipState.dismiss()
tooltipState.onDispose() /// <---- HERE
}
}) {
Text("Dismiss")
}
}
) {
}
},
state = tooltipState) {
IconButton(onClick = { }) {
Icon(imageVector = Icons.Filled.Call, contentDescription = "Your icon's description")
}
}
}

Một trường hợp khác mà trạng thái chú giải công cụ không được đặt lại là nếu thay vì tự gọi phương thức loại bỏ theo hành động của người dùng, người dùng nhấp vào bên ngoài chú giải công cụ, khiến chú giải công cụ bị loại bỏ. Điều này gọi phương thức loại bỏ ở hậu trường và trạng thái chú giải công cụ được đặt thành loại bỏ. Nhấn và giữ vào thành phần giao diện người dùng để xem lại chú giải công cụ của chúng tôi sẽ không mang lại kết quả gì.

Logic gọi phương thức onDispose của chú giải công cụ không được kích hoạt, vậy làm cách nào chúng tôi có thể đặt lại trạng thái của chú giải công cụ?
Hiện tại, tôi chưa thể tìm ra điều này. Nó có thể liên quan đến MutatorMutex của chú giải công cụ. Có thể với những bản phát hành sắp tới sẽ có API cho việc này. Tôi đã nhận thấy rằng nếu các chú giải công cụ khác xuất hiện trên màn hình và chúng được nhấn, thao tác này sẽ đặt lại chú giải công cụ đã nhấp vào trước đó.

Nếu bạn muốn xem mã được nêu ở đây, bạn có thể truy cập kho lưu trữ GitHub này
Nếu bạn muốn xem chú giải công cụ trong một ứng dụng, bạn có thể xem tại đây.
Tài liệu tham khảo
-
Tổng quan về chú giải công cụ Material3
-
Mặc định của chú giải công cụ
-
Mã nguồn chú giải công cụ
Học cách viết mã miễn phí. Chương trình giảng dạy mã nguồn mở của freeCodeCamp đã giúp hơn 40.000 người có được việc làm với tư cách là nhà phát triển. Bắt đầu