Android Tutorial
Software Setup and Configuration
Android Studio
File Structure
Components
Core Topics
Layout
View
Button
Intent and Intent Filters
Toast
RecyclerView
Fragments
Adapters
Other UI Component
Image Loading Libraries
Date and Time
Material Design
Bars
Working with Google Maps
Chart
Animation
Database
Advance Android
Jetpack
Architecture
App Publish
App Monetization
Jetpack Compose is Android's modern UI toolkit for native app development. With Compose, you can build UIs using Kotlin code, making it easier to define UI components and their interactions.
Let's see how you can create and manage a ProgressBar
using Jetpack Compose:
build.gradle
file and use the latest version of Compose:implementation "androidx.compose.ui:ui:x.x.x" implementation "androidx.compose.material:material:x.x.x"
Here's how you can create an indeterminate ProgressBar
:
import androidx.compose.material.CircularProgressIndicator import androidx.compose.runtime.Composable @Composable fun IndeterminateProgressBar() { CircularProgressIndicator() }
For a determinate ProgressBar
:
import androidx.compose.material.LinearProgressIndicator import androidx.compose.runtime.Composable @Composable fun DeterminateProgressBar(progress: Float) { LinearProgressIndicator(progress = progress) }
You can use it by passing a progress value between 0f and 1f:
DeterminateProgressBar(progress = 0.5f)
If you want to simulate a task being processed and update the ProgressBar
accordingly, you can use state in Compose:
import androidx.compose.runtime.* import kotlinx.coroutines.delay import kotlinx.coroutines.launch @Composable fun DynamicProgressBar() { var progress by remember { mutableStateOf(0f) } val coroutineScope = rememberCoroutineScope() // Simulate a task LaunchedEffect(key1 = Unit) { coroutineScope.launch { while (progress < 1f) { delay(100L) progress += 0.01f } } } LinearProgressIndicator(progress = progress) }
This DynamicProgressBar
function will increment its progress over time, simulating a task being completed.
Remember, Jetpack Compose emphasizes the importance of state and recomposition, so understanding how states trigger UI updates is crucial for building dynamic UI components.
Android ProgressBar example with Jetpack Compose:
import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.foundation.progressIndicator import androidx.compose.foundation.text.BasicText import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.material3.icons.Icons import androidx.compose.material3.icons.filled.HourglassEmpty import androidx.compose.material3.icons.filled.Refresh import androidx.compose.material3.icons.filled.TrendingFlat import androidx.compose.material33.Icon import androidx.compose.material3.setContentColor import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.rotate import androidx.compose.ui.graphics.Color import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.example.featherandroidtasks.ui.theme.FeatherAndroidTasksTheme @Composable fun ProgressBarExample() { var progress by remember { mutableStateOf(0.5f) } Column( modifier = Modifier .fillMaxSize() .padding(16.dp) ) { BasicText(text = "Progress: ${(progress * 100).toInt()}%", style = MaterialTheme.typography.h5) Spacer(modifier = Modifier.height(16.dp)) LinearProgressIndicatorExample(progress = progress) Spacer(modifier = Modifier.height(16.dp)) CircularProgressBarExample(progress = progress) Spacer(modifier = Modifier.height(16.dp)) IndeterminateProgressBarExample() Spacer(modifier = Modifier.height(16.dp)) ProgressBarWithStateExample() } } @Composable fun LinearProgressIndicatorExample(progress: Float) { LinearProgressIndicator( modifier = Modifier .fillMaxWidth() .height(8.dp), progress = progress ) } @Composable fun CircularProgressBarExample(progress: Float) { Box( modifier = Modifier .size(100.dp) .background(Color.Gray, shape = MaterialTheme.shapes.medium) .padding(16.dp) ) { CircularProgressIndicator( modifier = Modifier .fillMaxSize() .padding(4.dp) .clip(MaterialTheme.shapes.medium) .background(MaterialTheme.colorScheme.surface), progress = progress, color = MaterialTheme.colorScheme.primary ) } } @Composable fun IndeterminateProgressBarExample() { CircularProgressIndicator( modifier = Modifier .size(50.dp) .padding(16.dp) ) } @Composable fun ProgressBarWithStateExample() { var isLoading by remember { mutableStateOf(true) } if (isLoading) { CircularProgressIndicator( modifier = Modifier .size(50.dp) .padding(16.dp) ) } else { Icon(imageVector = Icons.Default.Refresh, contentDescription = null) } Spacer(modifier = Modifier.height(16.dp)) // Simulate a button click to toggle loading state IconToggleButton(checked = isLoading, onCheckedChange = { isLoading = it }) { BasicText(text = "Toggle Loading") } } @Preview(showBackground = true) @Composable fun PreviewProgressBarExample() { FeatherAndroidTasksTheme { Surface { ProgressBarExample() } } }
Circular ProgressBar in Jetpack Compose:
@Composable fun CircularProgressBarExample() { CircularProgressIndicator( modifier = Modifier .size(50.dp) .padding(16.dp) ) }
Customizing ProgressBar in Jetpack Compose:
Customize the ProgressBar appearance using modifiers:
LinearProgressIndicator( modifier = Modifier .fillMaxWidth() .height(8.dp) .background(Color.Gray, shape = MaterialTheme.shapes.medium) .padding(16.dp), progress = progress )
Indeterminate ProgressBar in Jetpack Compose:
Use the CircularProgressIndicator
without specifying the progress value:
CircularProgressIndicator( modifier = Modifier .size(50.dp) .padding(16.dp) )
Jetpack Compose LinearProgressIndicator example:
Use LinearProgressIndicator
to create a linear progress bar:
LinearProgressIndicator( modifier = Modifier .fillMaxWidth() .height(8.dp), progress = progress )
ProgressBar with animation in Jetpack Compose:
Apply animation to the ProgressBar using the animateFloatAsState
function:
var progress by remember { mutableStateOf(0.5f) } LinearProgressIndicator( modifier = Modifier .fillMaxWidth() .height(8.dp) .background(Color.Gray, shape = MaterialTheme.shapes.medium) .padding(16.dp), progress = progress ) LaunchedEffect(key1 = progress) { animateFloatAsState( targetValue = progress, animationSpec = tween(durationMillis = 1000) ).value.let { animatedProgress -> progress = animatedProgress } }
Updating ProgressBar dynamically in Jetpack Compose:
Update the ProgressBar value dynamically using mutable state:
var progress by remember { mutableStateOf(0.5f) } // Update progress dynamically progress = 0.7f LinearProgressIndicator( modifier = Modifier .fillMaxWidth() .height(8.dp), progress = progress )
Jetpack Compose ProgressBar with state:
Toggle the loading state of ProgressBar using mutable state:
var isLoading by remember { mutableStateOf(true) } if (isLoading) { CircularProgressIndicator( modifier = Modifier .size(50.dp) .padding(16.dp) ) } else { // Display other content when not loading } // Simulate a button click to toggle loading state IconToggleButton(checked = isLoading, onCheckedChange = { isLoading = it }) { BasicText(text = "Toggle Loading") }
ProgressBar in a Compose ViewModel:
Use a ViewModel to manage ProgressBar state:
class MyViewModel : ViewModel() { private val _isLoading = mutableStateOf(true) val isLoading: State<Boolean> = _isLoading // Methods to update loading state } @Composable fun ProgressBarInViewModelExample(viewModel: MyViewModel = viewModel()) { if (viewModel.isLoading.value) { CircularProgressIndicator( modifier = Modifier .size(50.dp) .padding(16.dp) ) } else { // Display other content when not loading } // Use viewModel.isLoading in UI }
Jetpack Compose ProgressBar with LiveData:
Use LiveData to observe and update ProgressBar state:
class MyViewModel : ViewModel() { val isLoading: LiveData<Boolean> = // LiveData instance // Methods to update loading state } @Composable fun ProgressBarWithLiveDataExample(viewModel: MyViewModel = viewModel()) { if (viewModel.isLoading.observeAsState(initial = true).value) { CircularProgressIndicator( modifier = Modifier .size(50.dp) .padding(16.dp) ) } else { // Display other content when not loading } // Use viewModel.isLoading in UI }
Styling and theming ProgressBar in Jetpack Compose:
Customize the style and theme of the ProgressBar:
LinearProgressIndicator( modifier = Modifier .fillMaxWidth() .height(8.dp) .background(Color.Gray, shape = MaterialTheme.shapes.medium) .padding(16.dp), progress = progress, color = MaterialTheme.colorScheme.primary )
Jetpack Compose ProgressBar and Coroutine example:
Use coroutines to perform asynchronous operations and update ProgressBar:
var progress by remember { mutableStateOf(0.5f) } LinearProgressIndicator( modifier = Modifier .fillMaxWidth() .height(8.dp) .background(Color.Gray, shape = MaterialTheme.shapes.medium) .padding(16.dp), progress = progress ) LaunchedEffect(key1 = progress) { // Perform async operation withContext(Dispatchers.IO) { // Simulate background work delay(3000) } // Update progress progress = 1.0f }
Jetpack Compose ProgressBar with percentage display:
Display progress percentage along with the ProgressBar:
var progress by remember { mutableStateOf(0.5f) } LinearProgressIndicator( modifier = Modifier .fillMaxWidth() .height(8.dp) .background(Color.Gray, shape = MaterialTheme.shapes.medium) .padding(16.dp), progress = progress ) BasicText(text = "Progress: ${(progress * 100).toInt()}%", style = MaterialTheme.typography.h6)