1 /*
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package com.android.settingslib.spa.widget.ui
18
19 import androidx.compose.foundation.Canvas
20 import androidx.compose.foundation.layout.Box
21 import androidx.compose.foundation.layout.fillMaxSize
22 import androidx.compose.foundation.layout.fillMaxWidth
23 import androidx.compose.foundation.layout.height
24 import androidx.compose.foundation.layout.padding
25 import androidx.compose.foundation.layout.size
26 import androidx.compose.foundation.progressSemantics
27 import androidx.compose.material3.CircularProgressIndicator
28 import androidx.compose.material3.MaterialTheme
29 import androidx.compose.runtime.Composable
30 import androidx.compose.ui.Alignment
31 import androidx.compose.ui.Modifier
32 import androidx.compose.ui.geometry.CornerRadius
33 import androidx.compose.ui.geometry.Offset
34 import androidx.compose.ui.geometry.Size
35 import androidx.compose.ui.graphics.Color
36 import androidx.compose.ui.graphics.drawscope.DrawScope
37 import androidx.compose.ui.unit.LayoutDirection
38 import androidx.compose.ui.unit.dp
39
40 /**
41 * Determinate linear progress bar. Displays the current progress of the whole process.
42 *
43 * Rounded corner is supported and enabled by default.
44 */
45 @Composable
LinearProgressBarnull46 fun LinearProgressBar(
47 progress: Float,
48 height: Float = 4f,
49 roundedCorner: Boolean = true
50 ) {
51 Box(modifier = Modifier.padding(top = 8.dp, bottom = 8.dp)) {
52 val color = MaterialTheme.colorScheme.onSurface
53 val trackColor = MaterialTheme.colorScheme.surfaceVariant
54 Canvas(
55 Modifier
56 .progressSemantics(progress)
57 .fillMaxWidth()
58 .height(height.dp)
59 ) {
60 drawLinearBarTrack(trackColor, roundedCorner)
61 drawLinearBar(progress, color, roundedCorner)
62 }
63 }
64 }
65
DrawScopenull66 private fun DrawScope.drawLinearBar(
67 progress: Float,
68 color: Color,
69 roundedCorner: Boolean
70 ) {
71 val isLtr = layoutDirection == LayoutDirection.Ltr
72 val width = progress * size.width
73 drawRoundRect(
74 color = color,
75 topLeft = if (isLtr) Offset.Zero else Offset((1 - progress) * size.width, 0f),
76 size = Size(width, size.height),
77 cornerRadius = if (roundedCorner) CornerRadius(
78 size.height / 2,
79 size.height / 2
80 ) else CornerRadius.Zero,
81 )
82 }
83
DrawScopenull84 private fun DrawScope.drawLinearBarTrack(
85 color: Color,
86 roundedCorner: Boolean
87 ) = drawLinearBar(1f, color, roundedCorner)
88
89 /**
90 * Determinate circular progress bar. Displays the current progress of the whole process.
91 *
92 * Displayed in default material3 style, and rounded corner is not supported.
93 */
94 @Composable
95 fun CircularProgressBar(progress: Float, radius: Float = 40f) {
96 Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
97 CircularProgressIndicator(
98 progress = { progress },
99 modifier = Modifier.size(radius.dp, radius.dp),
100 )
101 }
102 }
103