관리 메뉴

나만을 위한 블로그

[Android Compose] 무한 캐러셀 구현하는 법 본문

Android/Compose

[Android Compose] 무한 캐러셀 구현하는 법

참깨빵위에참깨빵_ 2024. 12. 21. 19:33
728x90
반응형

※ 모든 코드는 예제기 때문에 실제로 사용하려면 리팩토링, 예외처리를 추가한다

※ 서버 통신 없이 앱에 저장된 이미지를 사용해 구현했다

 

이번엔 컴포즈를 사용해서 정해진 이미지들을 계속해서 표시하는 무한 캐러셀 예제를 확인한다.

실행하면 아래처럼 작동한다.

 

 

코드는 아래와 같다.

 

import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import com.example.composepractice.R
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

@Composable
fun InfiniteCarouselScreen(modifier: Modifier = Modifier) {
    val images = listOf(
        R.drawable.cupcake,
        R.drawable.donut,
        R.drawable.eclair,
        R.drawable.froyo,
    )
    val extendedImages = remember { listOf(images.last()) + images + listOf(images.first()) }
    val lazyListState = rememberLazyListState(initialFirstVisibleItemIndex = 1)
    val coroutineScope = rememberCoroutineScope()

    LaunchedEffect(lazyListState) {
        while (true) {
            delay(1000)
            coroutineScope.launch {
                val nextIndex = lazyListState.firstVisibleItemIndex + 1
                lazyListState.animateScrollToItem(nextIndex)

                if (nextIndex == extendedImages.size - 1) {
                    lazyListState.scrollToItem(1)
                }
            }
        }
    }

    LazyRow(
        state = lazyListState,
        modifier = modifier.fillMaxSize()
    ) {
        items(extendedImages) { imageResId ->
            Image(
                painter = painterResource(id = imageResId),
                contentDescription = null,
                modifier = Modifier.fillMaxSize()
            )
        }
    }
}

 

계속 오른쪽으로 사진이 스크롤돼야 하기 때문에 LazyRow를 사용했고 계속 같은 이미지들을 보여주기 위해 리스트의 마지막 이미지 + 리스트 이미지 + 리스트의 첫 번째 이미지를 저장해 둔다.

그리고 rememberCoroutineScope로 코루틴을 만들고 LaunchedEffect에서 1초 주기로 계속 다른 이미지를 표시한다. 보통 3~4초 정도 텀을 두고 표시하지만 지금은 사진이 바뀌는 걸 확인하기 위해 1초로 설정했다.

 

사진이 표시되다 보면 언젠가 리스트의 마지막 사진이 표시되는데, 이 때 scrollToItem()을 통해 다시 첫 아이템의 인덱스로 이동한다. 실제로 실행해 보면 알겠지만 scrollToItem()은 엄청 빠르게 실행되서 이걸 알기가 어렵고 그냥 무한 반복되어 표시되는 것으로 보인다.

 

사진 크기가 작아서 사진 하나가 표시될 때마다 우측에 다음 이미지의 왼쪽 부분이 조금 표시되는데 이건 Modifier를 본인의 프로젝트에 맞게 수정하면 화면이나 특정 영역에 꽉 차게 표시되도록 수정할 수 있을 것이다.

반응형
Comments