진행 상태 표시기

진행률 표시기는 작업 상태를 시각적으로 나타냅니다. 모션을 사용하여 데이터 로드 또는 처리와 같이 프로세스가 얼마나 완료되었는지 사용자에게 알립니다. 또한 처리 완료에 얼마나 근접했는지를 언급하지 않고 처리 중임을 나타낼 수도 있습니다.

진행률 표시기를 사용할 수 있는 다음 세 가지 사용 사례를 고려하세요.

  • 콘텐츠 로드: 네트워크에서 콘텐츠를 가져오는 동안(예: 사용자 프로필의 이미지 또는 데이터를 로드하는 경우)
  • 파일 업로드: 업로드 소요 시간에 관한 의견을 사용자에게 제공합니다.
  • 긴 처리: 앱에서 많은 양의 데이터를 처리하는 동안 완료된 총 데이터의 양을 사용자에게 알립니다.

Material Design에는 두 가지 유형의 진행률 표시기가 있습니다.

  • 확정: 정확히 얼마나 진행되었는지 표시합니다.
  • 미확정: 진행률과 상관없이 계속 애니메이션이 재생됩니다.

마찬가지로 진행 상태 표시기는 다음 두 가지 형식 중 하나를 취할 수 있습니다.

  • 선형: 왼쪽에서 오른쪽으로 채워지는 가로 막대입니다.
  • 원주: 원의 전체 둘레를 포괄할 때까지 획의 길이가 길어지는 원입니다.
원형 진행률 표시기와 선형 진행률 표시기
그림 1. 두 가지 유형의 진행 상황 표시기

API 노출 영역

Material Design과 일치하는 플로팅 작업 버튼을 만드는 데 사용할 수 있는 여러 컴포저블이 있지만 매개변수는 크게 다르지 않습니다. 유의해야 할 주요 매개변수는 다음과 같습니다.

  • progress: 표시기에 표시되는 현재 진행 상황입니다. 0.01.0 사이에 Float를 전달합니다.
  • color: 실제 표시기의 색상입니다. 즉, 진행률을 반영하고 진행률이 완료될 때 구성요소를 완전히 포함하는 구성요소의 부분입니다.
  • trackColor: 표시기가 그려지는 트랙의 색상입니다.

지표 결정

결정 표시기는 작업이 얼마나 완전한지 정확히 나타냅니다. LinearProgressIndicator 또는 CircularProgressIndicator 컴포저블을 사용하고 progress 매개변수의 값을 전달합니다.

다음 스니펫은 비교적 상세한 예를 보여줍니다. 사용자가 버튼을 누르면 앱은 진행률 표시기를 표시하고 progress 값을 점진적으로 늘리는 코루틴을 실행합니다. 이렇게 하면 진행률 표시기가 차례로 반복됩니다.

@Composable
fun LinearDeterminateIndicator() {
    var currentProgress by remember { mutableStateOf(0f) }
    var loading by remember { mutableStateOf(false) }
    val scope = rememberCoroutineScope() // Create a coroutine scope

    Column(
        verticalArrangement = Arrangement.spacedBy(12.dp),
        horizontalAlignment = Alignment.CenterHorizontally,
        modifier = Modifier.fillMaxWidth()
    ) {
        Button(onClick = {
            loading = true
            scope.launch {
                loadProgress { progress ->
                    currentProgress = progress
                }
                loading = false // Reset loading when the coroutine finishes
            }
        }, enabled = !loading) {
            Text("Start loading")
        }

        if (loading) {
            LinearProgressIndicator(
                progress = { currentProgress },
                modifier = Modifier.fillMaxWidth(),
            )
        }
    }
}

/** Iterate the progress value */
suspend fun loadProgress(updateProgress: (Float) -> Unit) {
    for (i in 1..100) {
        updateProgress(i.toFloat() / 100)
        delay(100)
    }
}

로드가 부분적으로 완료되면 이전 예의 선형 표시기는 다음과 같이 표시됩니다.

마찬가지로 원형 표시기는 다음과 같이 표시됩니다.

미확정 표시기

미확정 표시기는 작업이 얼마나 완료되었는지를 반영하지 않으며, 오히려 모션의 완료 정도를 지정하지는 않지만 모션을 사용하여 처리가 진행 중임을 사용자에게 나타냅니다.

미확정 진행률 표시기를 만들려면 LinearProgressIndicator 또는 CircularProgressIndicator 컴포저블을 사용하되 progress 값을 전달하지 마세요. 다음 예는 버튼을 눌러 미확정 표시기를 전환하는 방법을 보여줍니다.

@Composable
fun IndeterminateCircularIndicator() {
    var loading by remember { mutableStateOf(false) }

    Button(onClick = { loading = true }, enabled = !loading) {
        Text("Start loading")
    }

    if (!loading) return

    CircularProgressIndicator(
        modifier = Modifier.width(64.dp),
        color = MaterialTheme.colorScheme.secondary,
        trackColor = MaterialTheme.colorScheme.surfaceVariant,
    )
}

다음은 표시기가 활성 상태일 때 이 구현의 예입니다.

다음은 동일한 구현이지만 CircularProgressIndicator 대신 LinearProgressIndicator를 사용한 예입니다.

추가 리소스