Wenn ich meine letzte Artikel über Jetpack Compose geschrieben habe, habe ich dort festgestellt, dass Jetpack Compose einige (nach meiner Meinung) grundlegenden Komponenten fehlen lässt und dass eine davon die Tooltip-Funktion ist.
Zu dieser Zeit gab es keine integrierte Composable zum Anzeigen von Tooltips und es gab mehrere alternative Lösungen, die online kursierten. Das Problem mit diesen Lösungen war, dass sie nach der Veröffentlichung neuer Jetpack Compose-Versionen möglicherweise nicht mehr funktionierten. Dies war also nicht ideal und die Community war davon ausgehend, dass irgendwann in der Zukunft die Unterstützung für Tooltips hinzugefügt werden würde.
Ich freue mich sagen zu können, dass wir seit Version 1.1.0 von Compose Material 3 eine integrierte Tooltip-Unterstützung haben. 👏
Dies ist zwar großartig, aber seit der Veröffentlichung dieser Version ist bereits mehr als ein Jahr vergangen. Und mit den folgenden Versionen haben auch die API-Bereiche für Tooltips stark geändert.
Wenn Sie den Changelog anschauen, werden Sie sehen, wie die öffentlichen und internen APIs verändert wurden. Daher sollten Sie beachten, dass sich die Dinge bis zu der Zeit, an der Sie diesen Artikel lesen, möglicherweise weiter verändert haben, da alle Aspekte von Tooltips noch mit der Annotation ExperimentalMaterial3Api::class gekennzeichnet sind.
❗️ Die in diesem Artikel verwendete Version von Material 3 ist 1.2.1, die am 6. März 2024 veröffentlicht wurde
Tooltip-Arten
Wir haben jetzt Unterstützung für zwei verschiedene Arten von Tooltips:
-
Einfache Tooltip
- Einfacher Tooltip
Erweiterter Medientooltip
Vous pouvez utiliser le premier type pour fournir des informations sur un bouton icône qui ne serait pas évident autrement. Par exemple, vous pouvez utiliser un simple tooltip pour indiquer à l’utilisateur ce que représente le bouton icône.
Um einen Tooltip zu Ihrer Anwendung hinzuzufügen, verwenden Sie das TooltipBox Composable. Dieses Composable nimmt mehrere Argumente an:
fun TooltipBox(
positionProvider: PopupPositionProvider,
tooltip: @Composable TooltipScope.() -> Unit,
state: TooltipState,
modifier: Modifier = Modifier,
focusable: Boolean = true,
enableUserInput: Boolean = true,
content: @Composable () -> Unit,
)
Einige davon sollten Ihnen bekannt sein, wenn Sie bereits mit Composables gearbeitet haben. Ich werde diejenigen hervorheben, die für spezielle Anwendungsfall relevant sind:
-
positionProvider – Typ PopupPositionProvider und wird verwendet, um die Position des Tooltips zu berechnen.
-
tooltip – Hier können Sie das Design der Benutzeroberfläche des Tooltips festlegen.
-
state – Dieses enthält den Status, der mit einer bestimmten Tooltip-Instanz verbunden ist. Es bietet Methoden wie das Anzeigen/Verbergen des Tooltips und beim_INSTANZIEREN_ einer Instanz können Sie festlegen, ob der Tooltip beständig sein soll oder nicht (d.h. ob er auf dem Bildschirm bleiben soll, bis der Benutzer außerhalb des Tooltips einen Klick ausführt).
-
Inhalt – Dies ist die UI, die der Tooltip oben/unten anzeigt.
Hier ist ein Beispiel der Erstellung eines BasicTooltipBox mit allen relevanten Argumenten ausgefüllt:
@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 verfügt über eine integrierte Klasse namens TooltipDefaults. Sie können diese Klasse verwenden, um Argumente zu verwenden, die einen TooltipBox bilden. Zum Beispiel könnten Sie TooltipDefaults.rememberPlainTooltipPositionProvider verwenden, um den Tooltip korrekt in Bezug auf das Anker-Element positionieren.
Reicher Tooltip
Ein reicher Medientooltip nimmt mehr Platz ein als einfacher Tooltip und kann verwendet werden, um mehr Hintergrundinformationen über die Funktionalität eines Symbol-Knopfes zu bereitstellen. Wenn der Tooltip angezeigt wird, können Sie zu ihm Schaltflächen und Links hinzufügen, um weitere Erklärungen oder Definitionen bereitzustellen.
Er wird in einem ähnlichen Weise wie einfacher Tooltip, innerhalb einer TooltipBox, aber Sie verwenden die RichTooltip-Komponens.
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 = {
/* Klick-Ereignis des Symbol-Knopfes */
}) {
Icon(imageVector = tooltipIcon,
contentDescription = "Your icon's description",
tint = iconColor)
}
}
Einige Dinge, die Sie beim Reichen Tooltip beachten sollten:
-
Ein Reicher tooltip unterstützt ein Anzeigezeichen.
-
Sie können eine Aktion (das heißt, einen Knopf) zum Tooltip hinzufügen, um den Benutzern die Möglichkeit zu geben, mehr Informationen zu erhalten.
-
Sie können Logik hinzufügen, um den Tooltip zu verbergen.
Edge Cases
Wenn Sie Ihren Tooltip-Zustand als persistent markieren, bedeutet das, dass sobald der Benutzer mit der UI interagiert, die Ihren Tooltip anzeigt, bleibt er bis zum Drücken eines anderen Bereichs auf dem Bildschirm sichtbar.
Wenn Sie sich am oberen Beispiel eines Rich-Tooltips anschaut haben, könnten Sie bemerkt haben, dass wir einen Knopf zum Schließen des Tooltips hinzugefügt haben, sobald er geklickt wird.
Es gibt ein Problem, das passiert, wenn ein Benutzer auf diesen Knopf drückt. Da die Verarbeitung auf dem Tooltip durchgeführt wird, wird der Tooltip nicht erneut angezeigt, wenn ein Benutzer einen weiteren langen Drück auf das UI-Element auslöst, das diesen Tooltip aufruft. Dies bedeutet, dass der Zustand des Tooltips persistent ist, solange er verdient ist. So, wie können wir das lösen?
Um den Zustand des Tooltips zurückzusetzen, müssen wir die onDispose Methode aufrufen, die über den Tooltip-Zustand angeboten wird. Sobald wir das tun, wird der Tooltip-Zustand zurückgesetzt und der Tooltip wird wieder angezeigt, wenn der Benutzer auf das UI-Element einen langen Drück ausführt.
@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() /// <---- HIER
}
}) {
Text("Dismiss")
}
}
) {
}
},
state = tooltipState) {
IconButton(onClick = { }) {
Icon(imageVector = Icons.Filled.Call, contentDescription = "Your icon's description")
}
}
}
Ein weiteres Szenarium, in dem der Tooltip-Zustand nicht zurückgesetzt wird, ist, wenn stattdessen per Benutzereingabe auf die Dismiss-Methode zugegriffen wird, der Benutzer außerhalb des Tooltips klickt, was zu dessen Schließung führt. Dies führt hinter den Schemen zur Aufruf der Dismiss-Methode und der Tooltip-Zustand wird auf „geschlossen“ gesetzt. Ein langer Druck auf das UI-Element, um den Tooltip erneut zu sehen, hat leider keine Wirkung.
Unser Logik, die die onDispose-Methode des Tooltips aufruft, wird nicht aktiviert, also wie können wir den Tooltip-Zustand zurücksetzen?
Derzeit konnte ich das nicht erkennen. Es könnte mit dem MutatorMutex des Tooltips in Verbindung stehen. Vielleicht wird mit zukünftigen Releases eine API dafür verfügbar sein. Ich habe bemerkt, dass, wenn andere Tooltips auf dem Bildschirm vorhanden sind und sie geklickt werden, der zuvor geklickte Tooltip zurückgesetzt wird.
Wenn Sie den hier gezeigten Code sehen möchten, können Sie zu diesem GitHub-Repository
gehen. Wenn Sie Tooltips in einer Anwendung sehen möchten, können Sie das hier anschauen.
Referenzen
Source:
https://www.freecodecamp.org/news/how-to-use-tooltips-in-jetpack-compose/