Jetpack Compose实现类似Viewpager滚动
通过扩展Row实现简单的viewpager
fun Modifier.horizontalScroll( state: ScrollState, enabled: Boolean = true, flingBehavior: FlingBehavior? = null, reverseScrolling: Boolean = false ) = scroll( state = state, isScrollable = enabled, reverseScrolling = reverseScrolling, flingBehavior = flingBehavior, isVertical = false )
上面是compose水平滚动的方法 state 用来操作滚动条状态 flingBehavior 是手指释放后的惯性事件,通过自定义FlingBehavior 在手指释放的时候判断
fling类
@Composable fun pagerFlingBehavior(state: ScrollState,childNum: Int): FlingBehavior { val flingSpec = rememberSplineBasedDecay<Float>() return remember(flingSpec) { PagerFling(flingSpec, state,childNum = childNum) } } class PagerFling(private val flingDecay: DecayAnimationSpec<Float>,val state:ScrollState, var childNum:Int) : FlingBehavior { override suspend fun ScrollScope.performFling(initialVelocity: Float): Float { // come up with the better threshold, but we need it since spline curve gives us NaNs // Log.e("lin","velocity=$initialVelocity,value=${state.value},maxValue=${state.maxValue}") return if (abs(initialVelocity) >= 0f) { var velocityX = initialVelocity var childWidth = state.maxValue/(childNum-1) var destValue = 0f var childLeft = state.value%childWidth; if(abs(velocityX)<500){ if(childLeft<childWidth/2){ destValue = state.value.toFloat()-childLeft }else{ destValue = state.value.toFloat()-childLeft+childWidth; } }else{ if(velocityX<0) destValue = state.value.toFloat()-childLeft else destValue = state.value.toFloat()-childLeft+childWidth; } var velocityLeft = initialVelocity var startPos = state.value animate(state.value.toFloat(),destValue,0f){value, velocity -> velocityLeft = value-startPos scrollBy(velocityLeft) startPos = value.toInt() } velocityLeft } else { initialVelocity } } }
测试类
@Composable fun SwipeableSample() { var list = mutableListOf<String>() for (i in 0..10) list.add("$i") var width = LocalConfiguration.current.screenWidthDp var height = LocalConfiguration.current.screenHeightDp val state = rememberScrollState() ComposeLauncherTheme { Scaffold( topBar = { TopAppBar(backgroundColor = Color.Red) { Text(text = "Test Compose", color = Color.White ,fontSize = 22.sp, modifier = Modifier.offset(x=10.dp) ) } }, content = { Row(modifier = Modifier .width(width = width.dp) .horizontalScroll(state,flingBehavior = pagerFlingBehavior(state,list.size)) ) { repeat(list.size){ Text(text = "1111 $it", modifier = Modifier.width(width =width.dp).height(height = height.dp)) Log.e("lin","init $it") } } } ) }