HorizontalPagerにIndicatorをつける
前回、HorizontalPagerを配置しました。これに、インジケーターをつけていきます。
データ構造
前回と同じですが、天気予報は、以下のデータ構造をしています。
Forecast(天気予報)
└ List<AreaOverview>(地域データ一覧)
├ name(地域名)
├ code(地域コード)
└ overviews(今日と明日とあれば明後日の天気予報)
├ weatherCode(天気コード)
├ weather(天気の説明)
└ wind(風の説明)
地域データ一覧をHorizontalPagerに表示し、インジケーターには、地域名を表示しようと思います。
ForecastScreen.kt
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun ForecastPager(forecast: Forecast) {
val pagerState = rememberPagerState()
val pageCount = forecast.areaOverviews.count()
HorizontalPager(
pageCount = pageCount,
state = pagerState,
) { page ->
val areaOverview = forecast.areaOverviews[page]
LazyColumn {
items(items = areaOverview.overviews) { forecastOverview ->
ForecastOverviewBox(forecastOverview)
}
}
}
}
ForecastOverviewBoxは、「overviews(今日と明日とあれば明後日の天気予報)」の部分の表示Composeです。
ここにインジケーターをつけます。
ForecastScreen.kt
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun ForecastPager(forecast: Forecast) {
+ val coroutineScope = rememberCoroutineScope()
val pagerState = rememberPagerState()
val pageCount = forecast.areaOverviews.count()
+ LazyRow(
+ modifier = Modifier.fillMaxWidth(),
+ horizontalArrangement = Arrangement.Center,
+ ) {
+ items(pageCount) { page ->
+ val buttonColors = if (pagerState.currentPage == page) {
+ ButtonDefaults.filledTonalButtonColors()
+ } else {
+ ButtonDefaults.outlinedButtonColors()
+ }
+
+ Button(
+ modifier = Modifier.padding(4.dp),
+ border = BorderStroke(1.dp, MaterialTheme.colorScheme.primary),
+ colors = buttonColors,
+ shape = RoundedCornerShape(percent = 10),
+ onClick = {
+ if (pagerState.currentPage != page) {
+ coroutineScope.launch {
+ pagerState.animateScrollToPage(page)
+ }
+ }
+ },
+ ) {
+ Text(forecast.areaOverviews[page].areaName)
+ }
+ }
+ }
HorizontalPager(
pageCount = pageCount,
state = pagerState,
) { page ->
}
表示中ページかの判定は「if (pagerState.currentPage == page)」の部分です。
これがtrueの場合は塗りつぶしで、falseの場合は枠のみにしています。
ボタンをタップした際にページを切り替えている部分は、「pagerState.animateScrollToPage(page)」です。
scrollToPageだと、アニメーションなしで切り替わります。