[Jetpack Compose] Pull Refreshを実装する

画像は適当なものを入れておいてください。

Contents 非表示

実装

ImageViewModel

class ImageViewModel: ViewModel() {
	private val _images = MutableStateFlow<List<Int>>(listOf())
	val images: StateFlow<List<Int>> = _images

	private val _isRefreshing = MutableStateFlow(false)
	val isRefreshing: StateFlow<Boolean> = _isRefreshing

	init {
		initializeImages()
	}

	// 初期化
	private fun initializeImages() {
		updateImages()
	}

	// Pull Refresh
	fun refreshImages() {
		updateImages(isRefreshing = true)
	}

	// 表示画像を更新
	private fun updateImages(isRefreshing: Boolean = false) {
		viewModelScope.launch {
			if (isRefreshing) {
				_isRefreshing.emit(true)
			}

			val newList = List(5) {
				val randomIndex = Random.nextInt(1, 11)
				getDrawableResId(randomIndex)
			}
			_images.emit(newList)
			delay(1000)
			_isRefreshing.emit(false)
		}
	}

	// ランダムな画像を選ぶ
	@DrawableRes
	private fun getDrawableResId(index: Int): Int {
		return when (index) {
			1 -> R.drawable.img_portrait1
			2 -> R.drawable.img_portrait2
			3 -> R.drawable.img_portrait3
			4 -> R.drawable.img_portrait4
			5 -> R.drawable.img_portrait5
			6 -> R.drawable.img_portrait6
			7 -> R.drawable.img_portrait7
			8 -> R.drawable.img_portrait8
			9 -> R.drawable.img_portrait9
			10 -> R.drawable.img_portrait10
			else -> R.drawable.img_portrait1
		}
	}
}

MainActivity

@OptIn(ExperimentalMaterialApi::class)
@Composable
fun PullToRefreshBasicSample(
	modifier: Modifier = Modifier,
	imageViewModel: ImageViewModel = viewModel()
) {
	val images by imageViewModel.images.collectAsState()
	val isRefreshing by imageViewModel.isRefreshing.collectAsState()

	val state = rememberPullRefreshState(
		refreshing = isRefreshing,
		onRefresh = { imageViewModel.refreshImages() }
	)

	Box(modifier = modifier
		.fillMaxSize()
		.pullRefresh(state),
		contentAlignment = Alignment.Center
	) {
		LazyColumn(
			modifier = Modifier.fillMaxWidth(),
			contentPadding = PaddingValues(16.dp),
			verticalArrangement = Arrangement.spacedBy(12.dp)
		) {
			items(images) { imageRes ->
				Image(
					painterResource(id = imageRes),
					contentDescription = "Portrait Image",
					modifier = Modifier
						.fillMaxWidth()
						.height(200.dp)
						.clip(RoundedCornerShape(12.dp)),
					contentScale = ContentScale.Crop
				)
			}
		}
		PullRefreshIndicator(
			refreshing = isRefreshing,
			state = state,
			modifier = Modifier.align(Alignment.TopCenter)
		)
	}
}