As the Snackbar available in Google’s Compose Material library doesn’t offer a quick and intuitive way to display on-screen messages, requiring multiple steps like using a Scaffold
or a SnackbarHost
/ SnackbarHostState
combo and handling coroutines, the InfoBar Compose library acts as a Jetpack Compose Snackbar alternative, aiming to provide a quicker way to display Snackbar-style on-screen messages. Moreover, it offers multiple customization options through dedicated parameters.
How easy can it be?
Firstly, include the library in your module-level build.gradle
file:
repositories {
mavenCentral()
}
dependencies {
implementation 'com.radusalagean:info-bar-compose:1.0.0'
}
Afterwards, Display a simple message at the press of a button:
setContent {
YourAppTheme {
Box(Modifier.fillMaxSize().padding(16.dp)) {
var message: InfoBarMessage? by remember { mutableStateOf(null) }
Button(
modifier = Modifier.align(Alignment.Center),
onClick = { message = InfoBarMessage(text = "Example message") }
) {
Text("Show message")
}
InfoBar(offeredMessage = message) {
message = null
}
}
}
}
Let’s take this example and explain it step by step:
- Create a mutable state holder called
message
, which is of nullable typeInfoBarMessage
, andremember { ... }
it, since we declare it inside a composable, initializing it tonull
; - Assign the
message
to anInfoBarMessage
instance, describing the message you want to be displayed on the screen. There are multiple parameters available, ranging fromtext
toaction
(if you want to have an interactive button), all the way to color-specific parameters. For now, we’ll only pass a String for our text message; - Finally, declare the
InfoBar
composable in your UI tree. Similarly, there are multiple parameters available for you to customize, but this time we only pass the required arguments:offeredMessage
– Themessage
variable we declared and assigned earlieronDismiss
– Trailing lambda which is called when theInfoBar
is either timed out or dismissed by the user. We always have to null out theInfoBarMessage
instance here. This is part of the contract with the library, in order to ensure the expected behavior.
Customization options
Although the previous example shows what you can achieve with the minimum effort required from you, there are also a number of customization options at your disposal.
InfoBar composable signatures
The InfoBar
composable has 2 signatures:
- One for a standard version, which already has a layout defined, inspired by the Material design
Snackbar
. This composable has multiple parameters exposed, allowing for increased customizability of the predefined standard layout. - One for a generic version, allowing to pass a composable layout defined in the client app.
Most importantly, make sure to check the GitHub repository readme file, for all the available options.
What about animations?
At the time of writing this article, the official Snackbar
implementation does not expose ways for us to easily customize the animation type and animation duration, thus being stuck with a Fade + Scale combo timed at 150ms for the enter animation and 75ms for the exit animation. While these are the values InfoBar
also uses by default, in order to feel seamless and familiar to the end-user, you also have the option to customize these aspects. Therefore, some relevant parameters for animations are listed below:
- Alter the animation type:
fadeEffect
,fadeEffectEasing
scaleEffect
,scaleEffectEasing
slideEffect
,slideEffectEasing
- Change the transition duration:
enterTransitionMillis
exitTransitionMillis
Using the generic composable
If the standard InfoBar
signature does not entirely meet your requirements in terms of layout, you can use the generic InfoBar
signature, which allows you to pass a custom layout composable. For instance, this is just an implementation example, feel free to get as creative as you want. Here are the general steps you need to follow:
1. Extend the BaseInfoBarMessage
abstract class and define your custom message data structure:
class CustomMessage(
val textString: String,
val icon: ImageVector,
val iconColor: Color,
val textColor: Color = Color.Unspecified,
override val backgroundColor: Color? = null,
override val displayTimeSeconds: Int? = 4,
) : BaseInfoBarMessage() {
override val containsControls: Boolean = false
}
2. Declare the content
composable that defines your layout:
val content: @Composable (CustomMessage) -> Unit = { message ->
Row {
Icon(
modifier = Modifier.padding(8.dp).align(Alignment.CenterVertically),
imageVector = message.icon,
contentDescription = null,
tint = message.iconColor
)
Text(
modifier = Modifier.align(Alignment.CenterVertically),
text = message.textString,
color = message.textColor
)
}
}
3. Display the message:
setContent {
YourAppTheme {
Box(Modifier.fillMaxSize().padding(16.dp)) {
var message: CustomMessage? by remember { mutableStateOf(null) }
Button(
modifier = Modifier.align(Alignment.Center),
onClick = {
message = CustomMessage(
textString = "This is a custom message",
textColor = Color(0xFF414141),
icon = Icons.Rounded.Info,
iconColor = Color(0xFF27C54D),
backgroundColor = Color(0xFFE3F1E6)
)
}
) {
Text("Show message")
}
InfoBar(offeredMessage = message, content = content) {
message = null
}
}
}
}
Sample app
More complex usage examples are available in the sample app. Download from Google Play and check its source code.
Conclusion
While the Snackbar
implementation for Jetpack Compose offered by Google is definitely functional and works great if you use it within a Scaffold
, I think the InfoBar Compose library is a decent alternative for developers who want more customization freedom, as well as for those who want to show a Snackbar-style message with minimal coding effort. If you would rather use the Snackbar instead but aren’t sure how to do it, I found a short and to-the-point article that shows you how.
I also have a free 7-Hour Jetpack Compose course* on my YouTube channel, which you can watch here.
(*Chapter 15: Info Bar laid the groundwork and the idea for this library. Starting from that implementation presented in the video, I changed it to support increased customization options, used stable animation APIs, among other improvements and offered it as a stand alone library. 😉)
If you use this library and enjoy it, please support it by starring it on GitHub. 🌟