Jetpack Compose实现类似Viewpager滚动

Git地址

 

通过扩展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")
                  }
                }
            }
        )

    }

  

posted @ 2021-09-11 23:11  dikeboyR  阅读(1225)  评论(0编辑  收藏  举报