https://kotlinlang.org logo
#compose
Title
# compose
c

Colton Idle

11/19/2021, 5:46 AM
For anyone that's savy with animation. A technique I've been using a lot is Crossfade{ } with a Button and when that button is making a network call, it crossfades into a CircularProgressBar. My "problem" is that I want the progressBar to be in the dead center of where the Button would have been. Leaving me to think... Crossfade is the wrong thing to use? Any other approaches you all would try? The only thing that comes to mind to me is to instead just create a composable where I change the alpha of the Button, and the progressBar so that the button is still measured, it's just not visible. Edit: Actually I looked at the code for Crossfade, and internally it seems to be changing alpha (which makes sense, I just didn't think about it before). If that's the case though... why do the contents inside shift around like the composable was removed from the tree entirely?
a

Albert Chang

11/19/2021, 6:09 AM
After the fade animation only the content for current state will remain.
c

Colton Idle

11/19/2021, 6:29 AM
thanks for pointing that out. Created this gist for now so that it just retains the state and so everything works as I want it to. No more jumping! https://gist.github.com/ColtonIdle/ad8b60f320136c237166c3fa7cc3fd33
a

Abhinav Suthar

11/19/2021, 6:31 AM
Not an answer to your question But I have created custom implementation of primary button for my app.
Copy code
@Composable
private fun RowScope.ButtonContent(
    text: String,
    isLoading: Boolean = false,
    @DrawableRes iconStart: Int? = null,
    @DrawableRes iconEnd: Int? = null,
) {
    if (isLoading) {
        CircularProgressIndicator(color = MegaTheme.colors.primary, modifier = Modifier.size(22.dp), strokeWidth = 2.dp)
    } else {
        if (iconStart != null) {
            Icon(painter = painterResource(id = iconStart), contentDescription = null)
            Spacer8()
        }
        Text(
            text = text,
            style = Typography.ButtonText
        )
        if (iconEnd != null) {
            Spacer8()
            Icon(painter = painterResource(id = iconEnd), contentDescription = null)
        }
    }
}
Copy code
@Composable
private fun BaseButton(
    text: String,
    colors: ButtonColors,
    modifier: Modifier = Modifier,
    showPlaceholder: Boolean = false,
    enabled: Boolean = true,
    isLoading: Boolean = false,
    elevation: ButtonElevation? = ButtonDefaults.elevation(),
    contentPadding: PaddingValues = ButtonDefaults.ContentPadding,
    @DrawableRes iconStart: Int? = null,
    @DrawableRes iconEnd: Int? = null,
    onClick: () -> Unit,
) {
    Button(
        onClick = onClick,
        modifier = modifier
            .animateContentSize()
            .shimmerWithCircularCorners(showPlaceholder),
        enabled = enabled && isLoading.not(),
        elevation = elevation,
        shape = RoundedCornerShape(50),
        colors = colors,
        contentPadding = contentPadding
    ) {
        ButtonContent(text, isLoading, iconStart, iconEnd)
    }
}
👍 1
So the BaseButton has loading state in it and I am using animateContentSize() modifer (please ignore the shimmer modifier). Though it might help someone.
c

Colton Idle

11/19/2021, 6:35 AM
Thanks. Yeah it seems like crossfade should have the ability to opt into this behavior IMO. Created this if anyone cares to star: https://issuetracker.google.com/issues/206972670