[Kotlin/Compose] Scroll Fade-In/Out animation

Scroll Fade-InOut animation

Scroll을 할 때, 각 item요소가 fade-in/out되면서 해당 위치로 이동하는 기능 구현을 해보았습니다.

미리보기

스르륵

 

 

구현

구현 방법

LazyColumn을 이용하여 열을 생성하고, 사용자가 스크롤하여 화면에 아이템이 보이게 되면, LaunchedEffect를 통해 alpha값을 변경하여 투명도 효과를 적용한다.

코드

class MainActivity : ComponentActivity() {  
    override fun onCreate(savedInstanceState: Bundle?) {  
        super.onCreate(savedInstanceState)  
        setContent {  
            FadeinscrollTheme {  
                // A surface container using the 'background' color from the theme  
                Surface(  
                    modifier = Modifier.fillMaxSize(),  
                    color = MaterialTheme.colorScheme.background  
                ) {  
                    scrollItems()  
                }  
            }        }    }  
}  

@Composable  
private fun scrollItems(modifier: Modifier = Modifier, itemList : List<String> = List(50){it -> it.toString()}){  
    val scrollState = rememberLazyListState()  
    LazyColumn(state = scrollState){  
        itemsIndexed(itemList){index, item ->  
            val animatableAlpha = remember { androidx.compose.animation.core.Animatable(0f) }  
            val isVisable = remember{  
                derivedStateOf {  
                    scrollState.firstVisibleItemIndex <= index  
                }  
            }            LaunchedEffect(isVisable.value){  
                if(isVisable.value){  
                    animatableAlpha.animateTo(  
                        1f, animationSpec = tween(durationMillis = 1000)  
                    )  
                }  
            }  
            scrollItem(content = item, alpha = animatableAlpha.value)  
        }  
    }}  


@Composable  
private fun scrollItem(modifier: Modifier = Modifier, content : String, alpha : Float){  
    Row(  
        modifier = modifier  
            .fillMaxWidth()  
            .background(color = Color.DarkGray.copy(alpha = alpha))  
            .padding(10.dp),  
        verticalAlignment = Alignment.CenterVertically  
    ){  
        Text(text = content,  
            color = Color.White,  
            modifier = Modifier.fillMaxWidth(),  
            textAlign = TextAlign.Center,  
            fontSize = 15.sp,  
            fontWeight = FontWeight.Bold  
            )  
    }  
}

단계 별 설명

1. ScrollItems

scrollItems함수는 LazyColumn을 사용하여 스크롤 가능한 아이템 리스트를 생성합니다.
itemList는 공유할 아이템의 개수로, 위의 코드에서는 0~49까지의 숫자를 문자열로 변환한 리스트를 사용하였습니다.

2. LazyColumn, ItemIndexed

LazyColumn은 스크롤이 가능한 열을 생성합니다.
itemsIndexeditemlist의 각 item에 대해 index와 함께 반복합니다.

3. Animatable 객체 초기화

Animatable객체를 LazyColumn안에 배치하여, 각 item에 대해 animatableAlpha 객체를 생성해주었습니다.
해당 객체는 각 item의 투명도를 결정하며, 초기값은 0f로 설정하였습니다.

여기서 1f는 완전 불투명이며, 0f는 완전 투명을 의미합니다.

4. isVisable

Animatable 객체와의 상호작용을 위한 isVisable 객체를 초기화해줍니다.
isVisable 객체의 경우에는 true/false 타입으로 화면에 보이는지 여부에 따라 결정이 됩니다.

derivedStateOf를 통해 scrollState.firstVisibleItemIndexindex보다 작거나 같은지, 즉 현재 화면에 보이는 첫 번째 item index 값이 현재 itemindex보다 크거나 같은지 여부를 판단합니다.

만약 indexfirstVisibleItemIndex보다 크거나 같으면, 화면에 보이는 것으로 간주하며, 만약 반대로 작다면, 보이지 않는 것으로 판단합니다.

이러한 로직을 통해 각 아이템이 현재 화면에 보이는지 여부에 따라 동적으로 업데이트를 할 수 있습니다.

5. LaunchedEffect

isVisable의 경우에는 isVisable.value값이 변경될 때 즉시 호출이 됩니다.
즉 위의 4번에서 설명한 로직처럼, visable상태가 바뀔 때 호출이 됩니다.

화면이 보이게 되는 경우에는 anmatableAlpha값을 1f로 바꾸어 화면에 보이도록 하였습니다. 이 때, timespec 1000으로 설정하여 1초동안 실행되도록 하였습니다.

 

깃허브

https://github.com/Myeongcheol-shin/fade-in-scroll/