본문 바로가기
Android/Kotlin

Jetpack Compose 에서 ProgressBar 구현하기

by wannagohome97 2024. 2. 5.

ProgressBar 를 Jetpack Compose 에서!

ProgressBar 는 통상적인 진행상황이나 로딩을 유저에게 보여줄 때 유용하게 사용되던
Android 의 View Widget 이었습니다... 만 Compose 로 넘어오며

CircularProgressIndicator 와 LinearProgressIndicator 로 분리되어 넘어오게 되었습니다.

 

 

장점?

영문 명에서 유추할 수 있듯이 기존 ProgressBar 보다 직관적이게 원형 / 선형 으로

처음부터 별개의 Composable 함수로 지원되고 있습니다.

 

그리고 간단한 색 / 디자인 정도만 바꾸려 해도 drawable 에서 layer-list 로 구현한 뒤 xml 에서 붙여넣거나 해야 했던 기존과는 다르게 Compose 답게 디자인하기가 매우 편합니다

 

구현은 아래와 같습니다.

@Composable
fun ProgressScreen(
    progress: MutableFloatState
    ){
    Box(modifier = Modifier.fillMaxSize()){
        CircularProgressIndicator(
            modifier = Modifier
                .size(75.dp)
                .align(Alignment.Center)
                .offset(y = -37.dp),
            color = Purple40,
            strokeWidth = 5.dp,
            trackColor = Purple80,
            strokeCap = StrokeCap.Round,
            progress = {
                progress.floatValue
            }
        )


        Text(
            modifier = Modifier
                .wrapContentHeight()
                .align(Alignment.Center)
                .offset(y = 37.dp),
            text = "${(progress.floatValue*100).toInt()}%",
            maxLines = 1)
    }
}

 

기본적인 화면 구성입니다.

이전에는 layer-list 에서 Attribute 의 Id 를 Override 하여 디자인을 덧씌웠지만 지금은

  • strokeWidth(ProgressBar 의 두께)
  • trackColor(ProgressBar 에서 진행도 부분에 대한 색상)
  • strokeCap(ProgressBar 에서 진행도 부분의 끝 마무리)
  • color(ProgressBar 의 색상)
라이브러리의 공식 설명은 이러합니다.
* @param color color of this progress indicator
* @param strokeWidth stroke width of this progress indicator
* @param trackColor color of the track behind the indicator, visible when the progress has not
* reached the area of the overall indicator yet
* @param strokeCap stroke cap to use for the ends of this progress indicator

 

 

아무튼 이 4가지의 Parameter 로도 아래와 같은 간단한 디자인이 가능합니다.

 

위에서 만들어둔 Composable 함수는 아래와 같이 사용하시면 됩니다.

 

    val start = remember {
        mutableStateOf(false)
    }
    val progress = remember {
        mutableFloatStateOf(0f)
    }
    if (!start.value){
        start.value = true
        progressViewModel.setUp{
            onProgressed = {floatValue ->
                progress.floatValue = floatValue
            }
        }
    }
    ProgressScreen(progress = progress)

 

fun setUp(onProgressed:(Float) -> Unit){
    /*
    여기선 예시로 1초동안 한 바퀴를 채우는 형태로 구현해보았습니다.
    실제로 사용하실 땐 Progress 가 정의될 때 마다 onProgressed 를 호출해서 value 를 교체해주면 됩니다.
    */
    var i = 0f
    while (i <= 1f){
        i += 0.001f
        delay(1)
        onProgressed(i)
    }
}