Accompagnist.kt (2395B) - raw
1 package me.rhunk.snapenhance.ui.util 2 3 import androidx.compose.foundation.ExperimentalFoundationApi 4 import androidx.compose.foundation.pager.PagerState 5 import androidx.compose.material3.TabPosition 6 import androidx.compose.ui.Modifier 7 import androidx.compose.ui.layout.layout 8 import androidx.compose.ui.unit.Constraints 9 import androidx.compose.ui.unit.lerp 10 11 //https://github.com/google/accompanist/blob/main/pager-indicators/src/main/java/com/google/accompanist/pager/PagerTab.kt#L78 12 @OptIn(ExperimentalFoundationApi::class) 13 fun Modifier.pagerTabIndicatorOffset( 14 pagerState: PagerState, 15 tabPositions: List<TabPosition>, 16 pageIndexMapping: (Int) -> Int = { it }, 17 ): Modifier = layout { measurable, constraints -> 18 if (tabPositions.isEmpty()) { 19 // If there are no pages, nothing to show 20 layout(constraints.maxWidth, 0) {} 21 } else { 22 val currentPage = minOf(tabPositions.lastIndex, pageIndexMapping(pagerState.currentPage)) 23 val currentTab = tabPositions[currentPage] 24 val previousTab = tabPositions.getOrNull(currentPage - 1) 25 val nextTab = tabPositions.getOrNull(currentPage + 1) 26 val fraction = pagerState.currentPageOffsetFraction 27 val indicatorWidth = if (fraction > 0 && nextTab != null) { 28 lerp(currentTab.width, nextTab.width, fraction).roundToPx() 29 } else if (fraction < 0 && previousTab != null) { 30 lerp(currentTab.width, previousTab.width, -fraction).roundToPx() 31 } else { 32 currentTab.width.roundToPx() 33 } 34 val indicatorOffset = if (fraction > 0 && nextTab != null) { 35 lerp(currentTab.left, nextTab.left, fraction).roundToPx() 36 } else if (fraction < 0 && previousTab != null) { 37 lerp(currentTab.left, previousTab.left, -fraction).roundToPx() 38 } else { 39 currentTab.left.roundToPx() 40 } 41 val placeable = measurable.measure( 42 Constraints( 43 minWidth = indicatorWidth, 44 maxWidth = indicatorWidth, 45 minHeight = 0, 46 maxHeight = constraints.maxHeight 47 ) 48 ) 49 layout(constraints.maxWidth, maxOf(placeable.height, constraints.minHeight)) { 50 placeable.placeRelative( 51 indicatorOffset, 52 maxOf(constraints.minHeight - placeable.height, 0) 53 ) 54 } 55 } 56 }