如何在 Horizontal Pager Android Compose 中实现淡入/淡出动画

问题描述 投票:0回答:2

我正在使用谷歌伴奏寻呼机在 Android Jetpack Compose 中设计水平寻呼机 (实现“com.google.accompanist:accompanist-pager:0.24.2-alpha”)。 我正确地实现了这个水平寻呼机。但我想将寻呼机的默认动画从水平向左/向右滑动更改为淡入/淡出动画。我是新作曲,我在互联网上没有找到任何有用的资源。如果有人知道这可以帮助我找到正确的解决方案。预先感谢。

val pagerState = rememberPagerState()
    HorizontalPager(count = 3, state = pagerState
    ) { pagePosition ->
            PagerScreen(onBoardingData = onBoardingDataList[pagePosition])
    }

这里PagerScreen是每个屏幕的可组合函数。

Like this Gif I want fadein / fadeout for horizontal Pager

android android-studio kotlin android-viewpager android-jetpack-compose
2个回答
1
投票

使用推荐的

graphicsLayer
HorizontalPager
的解决方案:

val pagerState = rememberPagerState()
HorizontalPager(
    state = pagerState,
    modifier = Modifier.fillMaxWidth()
) { page ->
    val isRtl =
        LocalContext.current.resources.configuration.layoutDirection == LayoutDirection.RTL
    Item(
        // ...
        modifier = Modifier.graphicsLayer {
            val pageOffset =
                ((pagerState.currentPage - page) + pagerState.currentPageOffsetFraction)
            alpha = lerp(
                start = 0f,
                stop = 1f,
                fraction = 1f - pageOffset.absoluteValue.coerceIn(0f, 1f),
            )

            val fraction =
                if (pagerState.currentPage != page) -pageOffset else 1f - pageOffset
            translationX = lerp(
                start = size.width,
                stop = 0f,
                fraction = if (isRtl) 2f - fraction else fraction,
            )
        }
    )
}

0
投票

我不确定使用

HorizontalPager
是否有更好的解决方案,所以我使用
swipeable
修饰符完成了这个解决方案。

@ExperimentalMaterialApi
@Composable
fun SwipeableSampleScreen5() {
    val pages = listOf(
        596 to Color(203, 41, 61),
        801 to Color(107, 0, 141),
        492 to Color(40, 38, 149),
        718 to Color(56, 144, 244),
        550 to Color(60, 149, 159)
    )
    val swipeableState = rememberSwipeableState(0)

    // This Box is only to get the screen's width
    BoxWithConstraints(Modifier.fillMaxWidth()) {
        val widthPx = with(LocalDensity.current) {
            maxWidth.toPx()
        }
        // Each anchor of the swipeable is the index * screen width
        val anchors = remember(pages) {
            List(pages.size) { index ->
                -(index * widthPx) to index
            }.toMap()
        }
        // This Box is capturing the swipe gesture
        Box(
            modifier = Modifier
                .fillMaxSize()
                .swipeable(
                    state = swipeableState,
                    anchors = anchors,
                    thresholds = { _, _ -> FractionalThreshold(0.5f) },
                    orientation = Orientation.Horizontal,
                )
        ) {
            // swipeableState provides the current index and the next index
            val currentIndex = swipeableState.currentValue
            val nextIndex = swipeableState.progress.to

            // This Box is behind and will display the nextValue
            Box(
                Modifier
                    // graphicsLayer is applied to the content
                    .graphicsLayer { 
                        alpha = 1f
                    },
            ) {
                Box(
                    Modifier
                        .fillMaxSize()
                        .background(pages[nextIndex].second),
                    contentAlignment = Alignment.Center
                ) {
                    Text(
                        text = pages[nextIndex].first.toString(),
                        style = MaterialTheme.typography.h1.copy(color = Color.White),
                    )
                }
            }

            // This Box is showing the current value which will change 
            // the alpha during the swiping
            Box(
                Modifier
                    .graphicsLayer {
                        alpha = 1f - swipeableState.progress.fraction
                    },
            ) {
                Box(
                    Modifier
                        .fillMaxSize()
                        .background(pages[currentIndex].second),
                    contentAlignment = Alignment.Center
                ) {
                    Text(
                        text = pages[currentIndex].first.toString(),
                        style = MaterialTheme.typography.h1.copy(color = Color.White),
                    )
                }
            }
        }
    }
}

解决方案已评论,但为了更好地理解这篇文章对我帮助很大。

结果如下:

您可以在此处找到完整来源。

© www.soinside.com 2019 - 2024. All rights reserved.