Showing posts with label Progress indicators. Show all posts
Showing posts with label Progress indicators. Show all posts

Tuesday, January 4, 2022

Swipe to refresh

Swipe to refresh manually refreshes screen content with a user action or gesture.

package compose.material.theme

import androidx.compose.animation.core.FastOutSlowInEasing
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.rememberScrollState
import androidx.compose.material.LinearProgressIndicator
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawWithCache
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import com.google.accompanist.swiperefresh.SwipeRefresh
import com.google.accompanist.swiperefresh.SwipeRefreshState
import com.google.accompanist.swiperefresh.rememberSwipeRefreshState
import compose.material.theme.ui.theme.Purple40
import compose.material.theme.ui.theme.Purple80
import kotlinx.coroutines.delay


@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SwipeToRefreshDemo(navController: NavController) {
    val context = LocalContext.current
    var isRefreshing by remember { mutableStateOf(false) }
    val swipeRefreshState = rememberSwipeRefreshState(isRefreshing)


    Scaffold(
        topBar = {
            CenterAlignedTopAppBar(
                title = { Text("Swipe to refresh") },
                Modifier.background(Purple40),
                navigationIcon = {
                    IconButton(onClick = { /* doSomething() */
                        navController.navigateUp()
                    }) {
                        Icon(
                            imageVector = Icons.Filled.ArrowBack,
                            contentDescription = "Localized description"
                        )
                    }
                },
            )
        },
        content = {

            Column {
                SwipeRefresh(
                    state = swipeRefreshState,
                    onRefresh = {
                        isRefreshing = true
                    },
                    indicator = { state, trigger ->
                        CustomViewPullRefreshView(state, trigger)
                    }
                ) {


                    // body content
                    val scrollState = rememberScrollState()
                    BlogContentSimple(scrollState)

                    // 2 sec delay
                    LaunchedEffect(isRefreshing) {
                        if (isRefreshing) {
                            delay(2000L)
                            isRefreshing = false
                        }
                    }
                }
            }


        }
    )

}

@Composable
fun CustomViewPullRefreshView(
    swipeRefreshState: SwipeRefreshState,
    refreshTriggerDistance: Dp,
    color: Color = Purple80
) {
    Box(
        Modifier
            .drawWithCache {
                onDrawBehind {
                    val distance = refreshTriggerDistance.toPx()
                    val progress = (swipeRefreshState.indicatorOffset / distance).coerceIn(0f, 1f)
                    val brush = Brush.verticalGradient(
                        0f to color.copy(alpha = 0.45f),
                        1f to color.copy(alpha = 0f)
                    )
                    drawRect(
                        brush = brush,
                        alpha = FastOutSlowInEasing.transform(progress)
                    )
                }
            }
            .fillMaxWidth()
            .height(80.dp)
    ) {
        if (swipeRefreshState.isRefreshing) {
            LinearProgressIndicator(
                Modifier.fillMaxWidth(),
                color = Purple80
            )
        } else {
            val trigger = with(LocalDensity.current) { refreshTriggerDistance.toPx() }
            val progress = (swipeRefreshState.indicatorOffset / trigger).coerceIn(0f, 1f)
            LinearProgressIndicator(
                progress = progress,
                modifier = Modifier.fillMaxWidth(),
                color = Purple40
            )
        }
    }
}



Accompanist SwipeRefresh library 
Utilities for Jetpack Compose : 
   implementation "com.google.accompanist:accompanist-swiperefresh:0.22.0-rc"

..

Wednesday, December 29, 2021

Progress indicators

Progress Bar is a component which tells user about the current ongoing process such as downloading, processing, verifying, etc

  • Linear Progress Indicator
  • Circular Progress Indicator

package io.material.compose.ui.design
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.requiredHeight
import androidx.compose.material.CircularProgressIndicator
import androidx.compose.material.LinearProgressIndicator
import androidx.compose.material.OutlinedButton
import androidx.compose.material.ProgressIndicatorDefaults
import androidx.compose.material.Text
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

@Composable
fun LinearProgressIndicatorSample() {
var progress by remember { mutableStateOf(0.1f) }
val animatedProgress by animateFloatAsState(
targetValue = progress,
animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec
)

Column(horizontalAlignment = Alignment.CenterHorizontally) {
LinearProgressIndicator(progress = animatedProgress)
Spacer(Modifier.requiredHeight(30.dp))
OutlinedButton(
onClick = {
if (progress < 1f) progress += 0.1f
}
) {
Text("Increase",style = MaterialTheme.typography.labelLarge)
}
}
}

@Composable
fun CircularProgressIndicatorSample() {
var progress by remember { mutableStateOf(0.1f) }
val animatedProgress by animateFloatAsState(
targetValue = progress,
animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec
)

Column(horizontalAlignment = Alignment.CenterHorizontally) {
CircularProgressIndicator(progress = animatedProgress)
Spacer(Modifier.requiredHeight(30.dp))
OutlinedButton(
onClick = {
if (progress < 1f) progress += 0.1f
}
) {
Text("Increase",style = MaterialTheme.typography.labelLarge)
}
}
}



..