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

ProressBar in Android using Jetpack Compose

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:

  • Setup: Ensure you have set up your project for Jetpack Compose. Add the required dependencies to your 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"

Indeterminate ProgressBar

Here's how you can create an indeterminate ProgressBar:

import androidx.compose.material.CircularProgressIndicator
import androidx.compose.runtime.Composable

@Composable
fun IndeterminateProgressBar() {
    CircularProgressIndicator()
}

Determinate ProgressBar

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)

Dynamic ProgressBar

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.

  1. 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()
            }
        }
    }
    
  2. Circular ProgressBar in Jetpack Compose:

    @Composable
    fun CircularProgressBarExample() {
        CircularProgressIndicator(
            modifier = Modifier
                .size(50.dp)
                .padding(16.dp)
        )
    }
    
  3. 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
    )
    
  4. Indeterminate ProgressBar in Jetpack Compose:

    Use the CircularProgressIndicator without specifying the progress value:

    CircularProgressIndicator(
        modifier = Modifier
            .size(50.dp)
            .padding(16.dp)
    )
    
  5. Jetpack Compose LinearProgressIndicator example:

    Use LinearProgressIndicator to create a linear progress bar:

    LinearProgressIndicator(
        modifier = Modifier
            .fillMaxWidth()
            .height(8.dp),
        progress = progress
    )
    
  6. 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
        }
    }
    
  7. 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
    )
    
  8. 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")
    }
    
  9. 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
    }
    
  10. 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
    }
    
  11. 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
    )
    
  12. 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
    }
    
  13. 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)