0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

スクロール可能なタブとページャー

Posted at

ScrollableTabRow

JetpackComposeでタブとページャーを組み合わせたサンプルを探すとTabRowを使ったものが多く見つかりますが、タブの数が多かったり可変だったりする場合はScrollableTabRowを使った方が便利です。
基本的にはTabRowScrollableTabRowに置き換えるだけで動作しますが、若干レイアウトを調整した方が良いと思います。

MainContent.kt

MainContent.kt
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun MainContent(
    modifier: Modifier = Modifier,
    state: MainContentState,
    onAction: (action: MainContentAction) -> Unit
) {
    val pagerState = rememberPagerState(initialPage = 0, pageCount = {state.itemCount})

    Column(
        modifier = modifier
    ) {
        ScrollableTabRow(
            selectedTabIndex = pagerState.currentPage,
            edgePadding = 0.dp,
        ) {
            for (i in 0 until  state.itemCount) {
                Box(
                    modifier = Modifier
                        .height(64.dp)
                        .clickable{
                            onAction(MainContentAction.ClickTab(i))
                        }
                        .padding(horizontal = 16.dp),
                    contentAlignment = Alignment.Center,
                ) {
                    Text(
                        text = "TabItem[${i}]",
                        style = MaterialTheme.typography.titleMedium,
                    )
                }
            }
        }
        HorizontalPager(
            modifier = Modifier.fillMaxSize(),
            state = pagerState
        ) { page ->
            Box(
                modifier = Modifier.fillMaxSize(),
                contentAlignment = Alignment.Center
            ) {
                Text(
                    text = "PagerItem[${page}]",
                    style = MaterialTheme.typography.headlineLarge
                )
            }
        }
    }

    LaunchedEffect(state.selectedIndex) {
        if (state.selectedIndex != pagerState.currentPage) {
            pagerState.animateScrollToPage(state.selectedIndex)
        }
    }
}

MainContentViewModel.kt

MainContentViewModel.kt
data class MainContentState(
    val selectedIndex: Int = 0,
    val itemCount: Int = 10
)

sealed interface MainContentAction {
    data class ClickTab(val index: Int): MainContentAction
}

class MainContentViewModel: ViewModel() {

    private val _state = MutableStateFlow(MainContentState())
    val state = _state.asStateFlow()

    fun onAction(action: MainContentAction) {
        when (action) {
            is MainContentAction.ClickTab -> clickTab(action.index)
        }
    }

    private fun clickTab(index: Int) {
        _state.update {
            _state.value.copy(
                selectedIndex = index
            )
        }
    }
}

MainActivity.kt

MainActivity.kt
+    val viewModel by viewModels<MainContentViewModel>()
+    val state by viewModel.state.collectAsState()
+
+    MainContent(
+        modifier = Modifier.padding(innerPadding),
+        state = state,
+        onAction = viewModel::onAction
+    )

動作イメージ

Screen_recording_20250227_150552-ezgif.com-video-to-gif-converter.gif

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?