1+ package app.grapheneos.camera.ui.composable.components
2+
3+ import androidx.compose.foundation.layout.padding
4+ import androidx.compose.material3.ExperimentalMaterial3Api
5+ import androidx.compose.material3.PlainTooltip
6+ import androidx.compose.material3.Text
7+ import androidx.compose.material3.TooltipBox
8+ import androidx.compose.material3.rememberTooltipState
9+ import androidx.compose.runtime.Composable
10+ import androidx.compose.runtime.remember
11+ import androidx.compose.ui.Modifier
12+ import androidx.compose.ui.unit.IntOffset
13+ import androidx.compose.ui.unit.IntRect
14+ import androidx.compose.ui.unit.IntSize
15+ import androidx.compose.ui.unit.LayoutDirection
16+ import androidx.compose.ui.unit.dp
17+ import androidx.compose.ui.unit.sp
18+ import androidx.compose.ui.window.PopupPositionProvider
19+ import kotlin.math.absoluteValue
20+
21+ @OptIn(ExperimentalMaterial3Api ::class )
22+ @Composable
23+ fun QuickTooltip (
24+ message : String ,
25+ tooltipAnchorVerticalSpacing : Float = 16.dp.toPx(),
26+ content : @Composable () -> Unit ,
27+ ) {
28+
29+ TooltipBox (
30+ positionProvider = remember {
31+ object : PopupPositionProvider {
32+ override fun calculatePosition (
33+ anchorBounds : IntRect ,
34+ windowSize : IntSize ,
35+ layoutDirection : LayoutDirection ,
36+ popupContentSize : IntSize
37+ ): IntOffset {
38+
39+ val anchorPopWidthDiff = anchorBounds.width - popupContentSize.width
40+
41+ val xOffset = if (anchorPopWidthDiff >= 0 ) {
42+ anchorBounds.left + anchorPopWidthDiff / 2
43+ } else if (
44+ (windowSize.width - anchorBounds.right >= anchorPopWidthDiff.absoluteValue / 2 )
45+ ) {
46+ anchorBounds.left - anchorPopWidthDiff.absoluteValue / 2
47+ } else {
48+ anchorBounds.right - popupContentSize.width
49+ }.toInt()
50+
51+ // Keep the tooltip below the view
52+ // (for use our case)
53+ //
54+ // Refer the source code of default implementation
55+ // if top based vertical offset is needed
56+ val yOffset = (anchorBounds.bottom + tooltipAnchorVerticalSpacing).toInt()
57+
58+ return IntOffset (xOffset, yOffset)
59+ }
60+ }
61+ },
62+ tooltip = {
63+ PlainTooltip {
64+ Text (
65+ message,
66+ fontSize = 14 .sp,
67+ modifier = Modifier
68+ .padding(
69+ vertical = 4 .dp,
70+ horizontal = 2 .dp,
71+ )
72+ )
73+ }
74+
75+ },
76+ state = rememberTooltipState(),
77+ content = content
78+ )
79+ }
0 commit comments