Skip to content

Commit a4cf140

Browse files
committed
refactor: implement Modifier.node
1 parent ccd92a5 commit a4cf140

File tree

1 file changed

+54
-0
lines changed

1 file changed

+54
-0
lines changed
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package to.bitkit.ui.shared.modifiers
2+
3+
import androidx.compose.foundation.gestures.detectHorizontalDragGestures
4+
import androidx.compose.runtime.remember
5+
import androidx.compose.ui.Modifier
6+
import androidx.compose.ui.composed
7+
import androidx.compose.ui.input.pointer.pointerInput
8+
import androidx.compose.ui.input.pointer.util.VelocityTracker
9+
10+
/**
11+
* Enables tab navigation via horizontal swipe gestures.
12+
*
13+
* Detects horizontal swipe velocity and navigates to adjacent tabs when the velocity
14+
* exceeds the specified threshold. Provides boundary protection to prevent navigation
15+
* beyond the first and last tabs.
16+
*
17+
* @param currentTabIndex The currently selected tab index (0-based)
18+
* @param tabCount Total number of tabs available for navigation
19+
* @param onTabChange Callback invoked when user swipes to change tabs, receives the new tab index
20+
* @param threshold Velocity threshold in pixels per second (default: 1500f)
21+
* Swipe velocity must exceed this value to trigger navigation
22+
*/
23+
fun Modifier.swipeToChangeTab(
24+
currentTabIndex: Int,
25+
tabCount: Int,
26+
onTabChange: (Int) -> Unit,
27+
threshold: Float = DEFAULT_SWIPE_THRESHOLD,
28+
): Modifier = composed {
29+
val velocityTracker = remember { VelocityTracker() }
30+
31+
pointerInput(currentTabIndex) {
32+
detectHorizontalDragGestures(
33+
onHorizontalDrag = { change, _ ->
34+
velocityTracker.addPosition(change.uptimeMillis, change.position)
35+
},
36+
onDragEnd = {
37+
val velocity = velocityTracker.calculateVelocity().x
38+
when {
39+
velocity >= threshold && currentTabIndex > 0 ->
40+
onTabChange(currentTabIndex - 1)
41+
42+
velocity <= -threshold && currentTabIndex < tabCount - 1 ->
43+
onTabChange(currentTabIndex + 1)
44+
}
45+
velocityTracker.resetTracking()
46+
},
47+
onDragCancel = {
48+
velocityTracker.resetTracking()
49+
},
50+
)
51+
}
52+
}
53+
54+
private const val DEFAULT_SWIPE_THRESHOLD = 1500f

0 commit comments

Comments
 (0)