🗒️

Jetpack Compose+Pagerで背景をグラデーションさせる

3 min read

アプリのチュートリアル画面において背景をグラデーションさせているものがあります。今回はJetpack Composeの環境でこれを実現してみたいと思います。

ライブラリ

JetPack ComposePagerを使うには以下のライブラリを導入します。

implementation 'com.google.accompanist:accompanist-pager:0.17.0'

Accompanistは、Jetpack Composeにはまだ実装されていない機能を補完したライブラリ群です。リンクは末尾に掲載しておきます。

実装

@ExperimentalPagerApi
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    
    val colorList = mutableListOf<Color>().apply {
        add(Color.Red)
        add(Color.Green)
        add(Color.Blue)
    }
    setContent {
        val pagerState = rememberPagerState(pageCount = 3)
        val backgroundColor = animateColorAsState(
            setPagerBackgroundColor(pagerState, colorList)
        )
	HorizontalPager(
	    state = pagerState, 
	    modifier = Modifier.background(backgroundColor.value)
	        .fillMaxWidth()
		.fillMaxHeight()
	    ) {
                Text(
		    text = it.toString(),
		    modifier = Modifier.fillMaxWidth().fillMaxHeight()
		)
            }
    }
}

@ExperimentalPagerApi
private fun setPagerBackgroundColor(
    pagerState: PagerState,
    colorList: List<Color>
): Color {
    return if (pagerState.isScrollInProgress) {
        if (pagerState.currentPageOffset >= 0) {
            val currentIndex = pagerState.currentPage + floor(pagerState.currentPageOffset).toInt()
            val nextIndex = if (pagerState.currentPage + floor(pagerState.currentPageOffset).toInt() != pagerState.pageCount - 1) {
                pagerState.currentPage + floor(pagerState.currentPageOffset).toInt() + 1
            } else {
                pagerState.currentPage + floor(pagerState.currentPageOffset).toInt()
            }
            Color(
                ColorUtils.blendARGB(
                    colorList[currentIndex].toArgb(),
                    colorList[nextIndex].toArgb(),
                    pagerState.currentPageOffset - floor(pagerState.currentPageOffset)
                )
            )
        } else {
            val currentIndex = pagerState.currentPage + ceil(pagerState.currentPageOffset).toInt()
            val previousIndex = if (pagerState.currentPage + ceil(pagerState.currentPageOffset).toInt() != 0) {
                pagerState.currentPage + ceil(pagerState.currentPageOffset).toInt() - 1
            } else {
                pagerState.currentPage + ceil(pagerState.currentPageOffset).toInt()
            }
            Color(
                ColorUtils.blendARGB(
                    colorList[previousIndex].toArgb(),
                    colorList[currentIndex].toArgb(),
                    pagerState.currentPageOffset - floor(pagerState.currentPageOffset)
                )
            )
        }
    } else {
        Color(colorList[pagerState.currentPage].toArgb())
    }
}

AccompanistPagerを作成する場合、HorizontalPagerまたはVerticalPagerを利用します。用途に合わせて選択してください。今回はHorizontalPagerを使っています。
animateColorAsStateでページごとに応じた色変更のアニメーションをつけます。背景色はPagerの現在位置およびオフセットで変更します。そしてbackgroundColorpagerModifiermodifier = Modifier.background(backgroundColor.value)として渡せばOKです。

デモ

リンク

https://github.com/google/accompanist/
https://google.github.io/accompanist/

Discussion

ログインするとコメントできます