🌀

[Android][Jetpack Compose] SwipeRefresh触ってみた

2022/07/29に公開

SwipeRefreshについて

2022年7月現在では accompanist に Swipe to Refresh を実現するライブラリが用意されています。
https://github.com/google/accompanist/tree/main/swiperefresh

build.gradle.kts
dependencies {
  implementation("com.google.accompanist:accompanist-swiperefresh:0.23.1")
}

※ライブラリを触っていた当時のstableなバージョンは 0.23.1 でしたが、先ほど見たら 0.25.0 だったので最新版と仕様が異なっている可能性があります。

実装

サンプル実装なので、ListItemの作りは良くないですが多めに見てください...。

@Composable
fun SampleScreen() {
    var refreshing by remember { mutableStateOf(false) }

    LaunchedEffect(refreshing) {
        if (refreshing) {
            delay(2000)
            refreshing = false
        }
    }

    Scaffold(topBar = {
        TopAppBar(
            title = { Text(text = "Sample") },
            navigationIcon = null,
            backgroundColor = Color.White
        )
    }) {
        Column(modifier = Modifier.fillMaxSize()) {
            SwipeRefresh(
                state = rememberSwipeRefreshState(isRefreshing = refreshing),
                onRefresh = {
                    refreshing = true
                }
            ) {
                LazyColumn {
                    items(count = 5) {
                        SampleColumn()
                    }
                }
            }
        }
    }
}

@Composable
fun SampleColumn() {
    Column(modifier = Modifier.fillMaxWidth()) {
        Row(
            modifier = Modifier.padding(
                horizontal = 16.dp,
                vertical = 32.dp
            )
        ) {
            Icon(
                imageVector = Icons.Default.AccountCircle,
                contentDescription = "icon",
                modifier = Modifier.size(36.dp)
            )
            Spacer(modifier = Modifier.padding(end = 16.dp))
            Text(
                text = "Column Sample",
                fontSize = 24.sp
            )
        }
        Divider()
    }
}

できました。

Listでない画面に SwipeRefresh を追加する場合

@Composable
fun SampleScreen() {

    var refreshing by remember { mutableStateOf(false) }

    LaunchedEffect(refreshing) {
        if (refreshing) {
            delay(2000)
            refreshing = false
        }
    }

    Scaffold(topBar = {
        TopAppBar(
            title = { Text(text = "Sample") },
            navigationIcon = null,
            backgroundColor = Color.White
        )
    }) {
        Column(modifier = Modifier.fillMaxSize()) {
            SwipeRefresh(
                state = rememberSwipeRefreshState(isRefreshing = refreshing),
                onRefresh = {
                    refreshing = true
                }
            ) {
                Column {
                    SampleColumn()
                    SampleColumn()
                    SampleColumn()
                }
            }
        }
    }
}

この場合、何度もスワイプしても SwipeRefresh のアイコンは表示されません。

解決策

SwipeRefresh 直下の Column に Modifier.verticalScroll() を適用します。

Column(modifier = Modifier.fillMaxSize()) {
            SwipeRefresh(
                state = rememberSwipeRefreshState(isRefreshing = refreshing),
                onRefresh = {
                    refreshing = true
                }
            ) {
                Column(
		  modifier = Modifier.verticalScroll(rememberScrollState())
		) {
                    SampleColumn()
                    SampleColumn()
                    SampleColumn()
                }
            }
        }

今度は SwipeRefresh のアイコンが表示されました!

Discussion