進行状況インジケーター

進行状況インジケーターには、オペレーションのステータスが表示されます。データの読み込みや処理などの処理がどの程度完了しているかをユーザーに示すために、モーションを使用します。また、処理が完了にどの程度近づいているかに関係なく、処理が行われていることを示すこともできます。

進行状況インジケーターを使用する次の 3 つのユースケースについて考えてみましょう。

  • コンテンツの読み込み: ユーザー プロファイルの画像やデータの読み込みなど、ネットワークからコンテンツを取得しているとき。
  • ファイルのアップロード: アップロードにかかる時間について、ユーザーにフィードバックを提供します。
  • 長時間処理: アプリが大量のデータを処理しているときに、合計データのうちどの程度の処理が完了しているかをユーザーに伝えます。

マテリアル デザインには、次の 2 種類の進行状況インジケーターがあります。

  • 決定: 進捗状況を正確に表示します。
  • 不確定: 進行状況に関係なく、継続的にアニメーション化します。

同様に、進行状況インジケーターには、次のいずれかの形式があります。

  • 線形: 左から右に塗りつぶされる水平バー。
  • : ストロークが長くなり、円の周囲を囲む円。
線形の進行状況インジケーターと円形の進行状況インジケーター。
図 1. 2 種類の進行状況インジケーター

API サーフェス

マテリアル デザインに沿ったフローティング アクション ボタンの作成に使用できるコンポーザブルがいくつかありますが、パラメータに大きな違いはありません。注意すべき主なパラメータは次のとおりです。

  • 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)を次に示します。

参考情報