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 46 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 66 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 84 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