I have a composable Icon here :
Icon(
painter =
if(condition) {
painterResource(id = .....)
}else{
//want to remove icon here
}
)
I want to remove the icon inside else statement. what should I put there?
Just remove the Icon.
if(condition){
Icon(painterResource(id = xxx),"contentDescription")
}
Related
Now the icon always in the start, what should I do to align the icon to the end? I tried to use modifier but doesn't work. Thank you in advance.
If you want an Icon aligned at the end in the TopAppBar use the actions parameter instead of the navigationIcon.
Something like:
TopAppBar(
title = { Text("Simple TopAppBar") },
backgroundColor = Red,
actions = {
// RowScope here, so these icons will be placed horizontally
IconButton(onClick = { /* doSomething() */ }) {
Icon(Icons.Filled.Close, contentDescription = null)
}
}
)
I have a slightly different expectation for padding to work. How can this problem be solved? I see this only at TopAppBar.
CenterAlignedTopAppBar(
title = { Text(title) },
modifier = Modifier.statusBarsPadding(), // or padding(top = 24.dp)
actions = {
if (isSync) {
IconButton(
onClick = { },
enabled = false,
content = {
Icon(
painter = painterResource(R.drawable.ic_outline_cloud_download_24),
contentDescription = title,
tint = Color.DarkGray.copy(alpha = alpha)
)
}
)
}
},
scrollBehavior = scrollBehavior
)
UPD
For example, here it works as it should -> link
I made it myself based on the source code. Not quite universal, but just right for me. I will not give the full code, it is in the source code. I will give only the place where it is necessary to add.
#Composable
private fun TopAppBarLayout(...) {
Layout(
...,
modifier = modifier.statusBarsPadding()
) {
...
}
}
The rest of the code is identical to the original.
UPDATE 21
Now everything works out of the box.
I am creating a dropdown menu where the items contain a text element and an icon (a spacer in between); but only the first text is shown completely. The icon is only visible when there is another item taking more space.
#Preview(showSystemUi = true)
#Composable
fun MyScreen() {
Box(Modifier.fillMaxSize(), Alignment.Center) {
Box() {
var expanded by remember { mutableStateOf(false) }
IconButton(onClick = { expanded = !expanded }) {
Icon(imageVector = Icons.Default.MoreVert, contentDescription = null)
}
DropdownMenu(expanded = expanded, onDismissRequest = { expanded = false }) {
MyMenuItem("item 1") // Icon visible
MyMenuItem("item 2") // Icon visible
MyMenuItem("item 3 long text") // Icon width shrunk to 0
MyMenuItem("item 4 long te") // Icon visible but shrunk
}
}
}
}
#Composable
fun MyMenuItem(text: String) {
DropdownMenuItem(onClick = { }) {
Text(text)
Spacer(modifier = Modifier.weight(1f))
Icon(imageVector = Icons.Default.Check, contentDescription = null) // <-- Icon
}
}
Note :
I have also tried using Row() and Surface() in place of DropdownMenuItem() but the result is similar.
Giving width to the MyMenuItem() works; but I want it to size itself automatically based on content.
Generally speaking, to create such a layout you just need to apply Modifier.weight(1f) to your Text.
You also need Modifier.width(IntrinsicSize.Max) for your Column to make the width equal to the widest item, but in your case it's already built into DropdownMenu.
But then this bug pops up, which doesn't allow you to properly size your MyMenuItem with Icon inside. Please put a star to draw more attention to it.
As a temporary solution until this bug is fixed, you can specify the size of the icon manually, like this:
// copied from the source code as it's internal
const val MaterialIconDimension = 24f
#Composable
fun MyMenuItem(text: String) {
DropdownMenuItem(
onClick = { }
) {
Text(text, Modifier.weight(1f))
Icon(
imageVector = Icons.Default.Check,
contentDescription = null,
modifier = Modifier.size(MaterialIconDimension.dp)
)
}
}
Result:
I have a few Icons in a row
Row {
IconButton {
Icon(
painter = painterResource(R.drawable.im1)
)
},
IconButton {
Icon(
painter = painterResource(R.drawable.im2)
)
}
}
But when it's displayed the distance between 2 icons in the row is bigger then I expect. I feel like there is 32dp spacer between them. How can I decrease the distance between 2 icons inside a row?
The space between the 2 icons it is not a padding and depends by the default size of the IconButton.
It is due to accessibility touch targets and allows the correct minimum touch target size.
You can change it disabling the LocalMinimumTouchTargetEnforcement and applying a Modifier.size(24.dp) to the IconButton:
CompositionLocalProvider(LocalMinimumTouchTargetEnforcement provides false){
Row {
IconButton(modifier = Modifier.size(24.dp),
onClick = {}) {
Icon(
painter = painterResource(R.drawable.ic_add_24px),""
)
}
IconButton(modifier = Modifier.size(24.dp),
onClick = {}) {
Icon(
painter = painterResource(R.drawable.ic_add_24px),""
)
}
}
}
As alternative you can use an Icon with the Modifier.clickable:
Row {
Icon(
painter = painterResource(R.drawable.ic_add_24px),"",
modifier = Modifier.clickable (onClick = {} )
)
Icon(
painter = painterResource(R.drawable.ic_add_24px),"",
modifier = Modifier.clickable (onClick = {} )
)
}
If you wish to control the exact distance, it is viable to implement a Layout, giving you complete control over the offset (yes you could also just use the offset Modifier, but I find this more promising.
Layout(
content = {
IconButton {
Icon(
painter = painterResource(R.drawable.im1)
)
},
IconButton {
Icon(
painter = painterResource(R.drawable.im2)
)
}
}
){ measurables, constraints ->
val icon1 = measurables[0].measure(constraints)
val icon2 = measurables[1].measure(constraints)
layout(constraints.maxWidth, constraints.maxHeight){ //Change these to suit your requirements
//Use place(x, y) to specify exact co-ordinates within the container
icon1.place(0, 0)
icon2.place(icon1.width, 0) //Places Directly where icon1 ends
/*If padding still appears, you can subtract some function from the second icon's starting point to make it even closer than the edge of iicon1
*/
}
This should be it!
How to change the color of the cut out for the bottom bar?
I know it takes the color from MaterialTheme.colors.background, but I don't want to change the background color for all components, only for the bottom bar. (The white color in the cut out in the picture.)
I have tried different things, for example setting a new theme just for the bottom bar, but that doesn't work.
val bottomBarColors = MaterialTheme.colors.copy(background = Color.LightGray)
...
bottomBar = {
MaterialTheme(
colors = bottomBarColors,
typography = MaterialTheme.typography,
shapes = MaterialTheme.shapes
) {
BottomAppBar(
cutoutShape = fabShape,
content = {
MyBottomNavigation(navController, bottomNavigationItems)
})
}
}
In your case you can apply the Modifier.background to the BottomAppBar:
bottomBar = {
BottomAppBar(
modifier = Modifier.background(Color.Red),
cutoutShape = fabShape) {
BottomNavigation {
/* .... */
}
}
}
The solution was easier than I thought. Just add something below the bottom bar:
bottomBar = {
Box {
Spacer(modifier = Modifier.matchParentSize().background(color = Color.Blue))
BottomAppBar(
cutoutShape = fabShape,
content = {
MyBottomNavigation(navController, bottomNavigationItems)
})
}
}