I'm currently working on a Header in Compose that uses LargeTopAppBar from Material 3. The issue is, that the title is not very customizable and neither is the scrolling animation(that uses nestedScroll). I would like to add a subtitle underneath the title that will not be shown in the smallTitle once the AppBar is collapsed. I would also like to know if there was a way to customize the actual animation of the title.
I know Material 3 is still in an Alpha but I would be very curious to see if there was some solution or workaround.
Thanks in advance!
LargeTopAppBar is a material3 composable which has its limitations in terms of customizability, but is easy to use.
If you need something different you can simply create a composable function for the topBar parameter in your screen scaffold which will implement all of the features you need.
Scaffold (
topBar = { customTopBar() }
) { innerPadding ->
YourScreen(modifier = modifier.padding(innerPadding))
}
In case you've already used a Scaffold in your code, you can simply use a when() statement and pass the appropriate composable for each screen!
For the subtitle you could use a simple column with two Texts,
Column {
Text(text = "Title")
if ( /* topBar state condition */ )
Text(text = "Subtitle")
}
and for the rest of the app bar you can have a Row that includes all elements (depending on your bar), like so:
Row(
verticalAlignment = Alignment.CenterVertically
horizontalArrangement = Arrangement.SpaceBetween
) {
Row {
IconButton(...) // For the back button
// Your title and subtitle Column()
Column {
Text(text = "Title")
if ( /* topBar state condition */ )
Text(text = "Subtitle")
}
}
// Rest of the IconButtons if needed
Row {
IconButton(...)
IconButton(...)
}
}
Apologies as I am not well versed in Jetpack Compose animation, but it should be easy enough to implement as their library is very simple to use, and you can always check the docs on their website.
Material3 elements are still in alpha but using simple surface/box/etc... elements you can make most custom designs that are needed.
Hope I was able to help!
Related
I want my scaffold to appear over the top of the notification bar, is this possible?
This is what I have (can't show much due to company policy):
I want the scaffold to go over the time and battery symbol.
This is what I want:
The above image is from Google Developers documentation site: https://developer.android.com/jetpack/compose/layouts/material#modal-drawers
My code:
Scaffold(
scaffoldState = scaffoldState,
topBar = {
TopBarComposable() // Where you see the Edit button is bottom right
},
drawerContent = {
DrawerContentComposable()
},
content = {
ContentComposable() // The main screen thats under the Top Bar Composable
},
bottomBar = { BottomBarComposable() },
drawerShape = RectangleShape
)
Any help would be greatly appreciated!
Use WindowCompat.setDecorFitsSystemWindows
// Turn off the decor fitting system windows, which allows us to handle insets, including IME animations
WindowCompat.setDecorFitsSystemWindows(window, false)
Source: Now In Android
Refer here for more details.
Note, you also have to handle padding manually.
i have the following snippet for showing a simple dialog with some text in Jetpack Compose on Android:
Dialog(onDismissRequest = { showDialog.value = false }) {
Text(
text = "Hello",
color = Color.Black,
fontSize = 24.sp,
modifier = Modifier
.background(
color = Color.Green,
shape = RoundedCornerShape(size = 16.dp)
)
.padding(8.dp)
)
}
which is producing the following output:
Now the tricky part starts: As the charming green rounded shape and the black text is defined, the white background at the edges is not. So where is this white background coming from?
The whole composable screen itself is wrapped into a custom theme at some other point. I already replaced every theme color to a different one to check if there is a change in the dialog's background.
I also tried wrapping the dialog itself in a second theme to override all other colors, but also without success.
Note: The white background is also there when i define a raw text composable without any styling, so it seems to be some kind of standard background of the dialog.
The goal is to have the white background color removed or replaced by a transparent color to only have the rounded shape on the dimmed background.
Thanks to everyone providing useful input, in the end the information that my code is working fine in different project setups made me think in a different direction.
So i tried to move my code some layers up and out of the theme definition. No other result.
But then it came to my mind that i have a mixed project with Compose and good old view implementations and therefore also some xml styles.
Digging a little bit deeper into the compose androidx.compose.ui.window.Dialog one can see that there is an invocation of R.style.DialogWindowTheme in the DialogWrapper. I'm not 100% sure, but i assume that my own xml definitions are overriding some properties of this style and affect the appearance of the compose dialog.
So if you also have similar troubles like i had check the following:
Do you use xml styles and compose in the same project?
Did you create a style for dialogs and override dialogTheme in your theme?
<item name="android:dialogTheme">#style/AppTheme.SomeDialogStyles</item>
Then please check if you set a custom background color
<item name="android:background">#color/some_color</item>
The solution for my issue was to remove the android:background attribute. Now i'm smoketesting all existing dialogs if this has some negative impact, but my issue with the white background in the compose dialog is solved!
Try this:
Dialog(
onDismissRequest = {
}
) {
Column(modifier = Modifier.background(color = Color.Transparent)) {
Text(
text = "Hello",
color = Color.Black,
fontSize = 24.sp,
modifier = Modifier
.background(
color = Color.Green,
shape = RoundedCornerShape(size = 16.dp)
)
.padding(8.dp)
)
}
}
I was try with Dialog and no way to clear flag WindowManager.LayoutParams.FLAG_DIM_BEHIND.
You can try to use Popup to replace Dialog, everything work good for me.
Popup(
onDismissRequest = {},
properties = PopupProperties(
focusable = true,
dismissOnBackPress = false,
dismissOnClickOutside = false,
excludeFromSystemGesture = true,
)
) {
Box(
contentAlignment = Alignment.Center,
modifier = Modifier
.fillMaxSize()
.background(Color.Transparent)
) {
// Your content code is here
}
}
I'm trying to make a bar graph, that has labels on some of them. Image of the bar as is right now.
The labels below each vertical bar is adding unwanted spacing between the bars.
I would like the remove that extra spacing between each bar, but I don't know how.
I made the bars with Jetpack Compose, like this (I removed most of the code. It isn't necessary to show in this case):
Column(
modifier = Modifier
.width(8.dp)
) {
Column(
modifier = modifier
) {
Box(
modifier = Modifier
)
Box(
modifier = Modifier
)
}
vText(
text = "21",
modifier = Modifier,
)
}
I added the bars in a Row().
I need a solution as to how I can make the space between each bar the same, but still be able to show the labels. I tried SpaceEvenly in the Row(), but that just cuts off the label.
I found a solution. I edited the Text() to include the modifier .wrapContentSize(unbounded = true).
Image of the result
In Jetpack Compose the clickable Modifier will by default use LocalIndication.current and show a ripple that is bound to the border. That looks great almost always, but there are some circumstances where a rounded, unbound ripple looks better. Back in View Android we would've used android:background="?attr/selectableItemBackgroundBorderless to achieve this behaviour. How can we do it in compose?
Example [source]:
You can customise the ripple effect as follow:
Modifier.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = rememberRipple(bounded = false), // You can also change the color and radius of the ripple
onClick = {}
)
I was trying Jetpack Compose on Android Studio Canary 1 and I added Column composable to the ui. Column has one property called modifier in which we can pass different modifiers. I used Expanded modifier which resulted in Column taking all the available space.
Also, Column has mainAxisSize and crossAxisSize properties so I tried them also and set it to LayoutSize.Expand which is intended to expand the given axis I think. This also resulted in Column taking all the available space. Check out the example below:
1. Using LayoutSize.Expand
Column(mainAxisSize = LayoutSize.Expand,
crossAxisSize = LayoutSize.Expand) {
Text("Jetpack",modifier = ExpandedHeight)
Text("Compose",modifier = ExpandedHeight)
}
Output:
2. Using Expanded
Column(modifier = Expanded) {
Text("Jetpack",modifier = ExpandedHeight)
Text("Compose",modifier = ExpandedHeight)
}
Output:
Observation is that Both the following code provides the same output.
Then what is the difference between Expanded and LayoutSize.Expand
when it comes to Column and Row?
They are two ways to achieve the same thing:
The Expanded modifier forces a target component to fill all available space. It can be applied to any composable that accepts a modifier.
The mainAxisSize parameter is a way to set the size of the layout, and is a parameter that is specific to Row/Column.
You should use the Expanded modifier. The mainAxisSize parameter is already removed from Column.
On jetpack compose 1.0, Expanded modifier which looks like flutter api is no longer available
But you can do it like this.
Row {
Box(modifier =
Modifier.weight(1f).wrapContentWidth(Alignment.Start)) {}
Box() {}
}
In the first Box composable, the layout is expanded. It's similar to flutter Flex widget if you familiar with flutter.
You can also view the google ref here https://developer.android.com/jetpack/compose/layouts/intrinsic-measurements