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

Thomas

01/07/2021, 9:05 PM
Is there a way to show a Snackbar with a custom Text but using the default positioning of the Scaffold SnackbarHost? When using
scaffoldState.snackbarHostState.showSnackbar
you can only set a String, but I would like to set a Text so I can style the text using annotated string builder. When just including a Snackbar without using Scaffold it appears at the top of the screen, which is not what I want (I would like it at the bottom how it is supposed to be). Looks like the Scaffold/SnackbarHost is setting the correct positions.
m

matvei

03/01/2021, 7:57 PM
You can pass your own SnackbarHost with custom Snackbar appearance in the scaffold is you desire so
t

Thomas

03/01/2021, 8:11 PM
@matvei thanks for your answer. I tried something like that which looks like the following. Is this really the correct way to do this?
Copy code
@Composable
fun Sample() {
    val scope = rememberCoroutineScope()
    val scaffoldState = rememberScaffoldState()
    Scaffold(
        scaffoldState = scaffoldState,
        snackbarHost = {
            SnackbarHost(it) { data ->
                if (data.message == "showCustomMessage") {
                    Snackbar {
                        Text(
                            text = buildAnnotatedString {
                                pushStyle(SpanStyle(fontWeight = FontWeight.Bold))
                                append(stringResource(R.string.my_custom_message))
                                pop()
                            }
                        )
                    }
                } else {
                    Snackbar(snackbarData = data)
                }
            }
        },
        content = {
            Button(
                onClick = {
                    scope.launch {
                        scaffoldState.snackbarHostState.showSnackbar("showCustomMessage")
                    }
                }
            ) {
                Text("Show snackbar")
            }
        }
    )
}
Because I need to create a snackbar myself, I cannot use the showSnackbar suspend function how it is supposed to be used. I am also missing padding around the snackbar.
I think something like this would make much more sense, but unfortunately that is not possible.
Copy code
@Composable
fun Sample() {
    val scope = rememberCoroutineScope()
    val scaffoldState = rememberScaffoldState()
    Scaffold(
        scaffoldState = scaffoldState,
        content = {
            Button(
                onClick = {
                    scope.launch {
                        // DOES NOT COMPILE
                        scaffoldState.snackbarHostState.showSnackbar(
                            message = {
                                Text(
                                    text = buildAnnotatedString {
                                        pushStyle(SpanStyle(fontWeight = FontWeight.Bold))
                                        append(stringResource(R.string.my_custom_message))
                                        pop()
                                    }
                                )
                            }
                        )
                    }
                }
            ) {
                Text("Show snackbar")
            }
        }
    )
}
m

matvei

03/01/2021, 8:23 PM
We're yet to support AnnotatedString in snackbar APIs. Please, file a feature request
As for the snipped with custom text above -- it seems like if you really want to have a AnnotatedString -- that's the way that will work for now. If you only want a bold text -- there's a
TextStyle
object for it
The idea why we didn't introduce the AnnotatedString in snackbars is because snackbars are essentially an in-app notification and mostly they should be the same in different apps for a better user experience, but I agree that sometimes it might be useful
t

Thomas

03/01/2021, 8:50 PM
I need to use AnnotatedString for the following. It's basically a message which shows which devices are connected to the app.
m

matvei

03/02/2021, 11:07 AM
Thanks a lot!
f

Filippo Vigani

12/07/2021, 2:14 PM
@matvei do you have any updates on this? Even passing some extra snackbar data would help, for instance if I wanted to have different snackbar colors for different message metadata (the simplest example is showing a red snackbar message for errors)
m

matvei

12/07/2021, 2:29 PM
We're considering some API changes in this regard in snackbar in material3 https://android-review.googlesource.com/c/platform/frameworks/support/+/1902091
For now we think of making an overload of
snowSnackbar
that accepts the arbitrary instance of the
SnackbarData
, so you can create your own custom
class MySnackbarWithMetadata: SnackbarData
and then you can do
Copy code
SnackbarHost(hostState) { data -> 
    if (data is MySnackbarWithMetadata) {
         // show custom snackbar
    } else {
         // show regular snackbar
    }
}
Not the cleanest solution for sure, but it unlocks any custom data propagation, while keeping you mostly in line with specs. Stay tuned 🙂
👍 1
16 Views