Items seem to have fixed height inside Column.
I'm trying to show multiple rows of dynamic height inside the column, and the items of those rows also having dynamic height.
I have tried wrapping the Column inside the box, but that doesn't work.
Box {
Column(
modifier = Modifier
.fillMaxSize()
) {
Image(
painter = painterResource(id = R.drawable.background_home),
contentDescription = "",
contentScale = ContentScale.FillBounds,
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight(0.3f)
)
Spacer(modifier = Modifier.height(10.dp))
List()
Spacer(modifier = Modifier.height(10.dp))
Row(
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight()
.padding(10.dp)
) {
Text(
text = "My Days",
style = TextStyle(
fontStyle = FontStyle.Normal,
fontFamily = FontFamily.Monospace,
fontWeight = FontWeight.Bold
)
)
Text(text = "Red Sun")
}
MyAnotherList(
Modifier
.fillMaxWidth()
.fillMaxHeight(0.6f)
.padding(10.dp)
.horizontalScroll(rememberScrollState())
)
Spacer(modifier = Modifier.height(10.dp))
Row(
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight()
.padding(10.dp)
) {
Text(
text = "My Other Days",
style = TextStyle(
fontStyle = FontStyle.Normal,
fontFamily = FontFamily.Monospace,
fontWeight = FontWeight.Bold
)
)
Text(text = "Blue Sun")
}
MyOtherList()
}
TopBar()
}
Trying to achieve something like this, but all the rows will have dynamic height
Is there a way that I can provide dynamic height to the items inside scrollable columns.
Related
I have the above UI Screen. In that layout the "Trash" icon should be aligned Vertically_centered , as of now its not Vertical Centered. How to achieve this in Jetpack compose without using Padding. Please find my code below in which I'm using a column with 2 rows in it.:
#Composable
fun DisplayShelfInfo(shelfHistoryItem: ShelfHistoryItem){
Column(modifier = Modifier
.fillMaxWidth()
.height(60.dp)
.padding(top = 5.dp , bottom = 5.dp)
.background(color = colorResource(R.color.row_back_ground)),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally) {
Row(modifier = Modifier
.fillMaxWidth()
.wrapContentHeight()){
Text(
text = stringResource(R.string.shelf_nr), color = Color.Black,
modifier = Modifier.padding(start = 16.dp)
)
Text(
text = (shelfHistoryItem.shelfId).toString(), color = Color.Black,
modifier = Modifier.padding(start = 16.dp)
)
Spacer(Modifier.weight(1f))
Image(
painter = painterResource(id = R.drawable.ic_delete),
modifier = Modifier
.padding(end = 5.dp)
.align(Alignment.CenterVertically)
.clickable {},
contentDescription = "Delete Image"
)
}
Row(modifier = Modifier
.fillMaxWidth()
.wrapContentHeight()){
Text(
text = shelfHistoryItem.noOfArticles.toString(), color = Color.Black,
modifier = Modifier.padding(start = 16.dp)
)
Text(
text = stringResource(R.string.article_count_label), color = Color.Black,
)
}
}
}
Move the Image out of Row, and use 2 Columns.
Something like:
Row(
modifier = Modifier
.height(IntrinsicSize.Min) //important
.background(Red),
) {
Column(
modifier = Modifier
.weight(1f)
.padding(top = 5.dp, bottom = 5.dp),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Row(
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight()
) {
Text(
text = "shelf_nr",
color = Color.Black,
modifier = Modifier.padding(start = 16.dp)
)
Text(
text = "shelfId", color = Color.Black,
modifier = Modifier.padding(start = 16.dp)
)
Spacer(Modifier.weight(1f))
}
Row(
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight()
) {
Text(
text = "shelfHistoryItem", color = Color.Black,
modifier = Modifier.padding(start = 16.dp)
)
Text(
text = "article_count_label", color = Color.Black,
)
}
}
Column(
modifier = Modifier.fillMaxHeight(), //important
verticalArrangement = Arrangement.Center,
) {
Image(
painter = painterResource(id = R.drawable.ic_menu_camera),
modifier = Modifier
.padding(end = 5.dp)
.clickable {},
contentDescription = "Delete Image"
)
}
}
I need to make layout that looks like this:
So I need to position two avatars in row while first avatar is going over second one. Also, icon for back is positioned on top of first avatar. I need basically something like position absolute but can not find how to do this with Jetpack compose.
You can use Box and zIndex to reach this result,
try this code you will get a result like that
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.background(Color.Yellow)
.padding(20.dp)
) {
Box {
Box(
contentAlignment = Alignment.TopStart,
modifier = Modifier
.height(30.dp)
.zIndex(3f)
) {
Icon(
imageVector = Icons.Rounded.ArrowBack,
contentDescription = "ArrowBack",
modifier = Modifier
.size(20.dp)
.clip(RoundedCornerShape(20.dp))
.background(Color.Gray)
.zIndex(2f)
.border(1.dp, Color.White, RoundedCornerShape(20.dp))
.padding(3.dp)
)
}
Box(
contentAlignment = Alignment.Center,
modifier = Modifier
.padding(start = 10.dp)
.size(30.dp)
.clip(RoundedCornerShape(20.dp))
.background(Color.Gray)
.zIndex(2f)
.border(1.dp, Color.White, RoundedCornerShape(20.dp))
.padding(6.dp)
) {
Icon(
imageVector = Icons.Rounded.Person,
contentDescription = "Person",
modifier = Modifier
.size(30.dp)
)
}
Box(
modifier = Modifier
.padding(start = 30.dp)
.size(30.dp)
.clip(RoundedCornerShape(20.dp))
.background(Color.Gray)
.zIndex(1f)
.border(1.dp, Color.White, RoundedCornerShape(20.dp))
.padding(6.dp)
) {
Icon(
imageVector = Icons.Rounded.Person,
contentDescription = "Person",
modifier = Modifier
.size(30.dp)
)
}
}
Spacer(modifier = Modifier.width(6.dp))
Text(text = "17 other answers")
}
How can we achieve this in jetpack compose
I'm doing something like this
Button(
elevation = ButtonDefaults.elevation(
defaultElevation = 0.dp,
pressedElevation = 8.dp,
disabledElevation = 0.dp
),
onClick = { onClick },
shape = RoundedCornerShape(28.dp),
modifier = modifier
.fillMaxWidth()
.shadow(0.dp),
contentPadding = PaddingValues(15.dp),
colors = ButtonDefaults.buttonColors(backgroundColor = Color.White),
border = BorderStroke(1.dp, Color.Grey)
) {
Box(modifier = modifier.fillMaxWidth(),
contentAlignment = Alignment.Center) {
Icon(
imageVector = imageVector,
modifier = Modifier
.size(18.dp),
contentDescription = "drawable icons",
tint = Color.Unspecified
)
Spacer(modifier = Modifier.width(10.dp))
Text(
text = buttonText,
color = Color.Black,
textAlign = TextAlign.Center
)
}
}
So as you can see the Google logo is just left of the text I need it at the start of the box so how can I do this.
You can use align(Alignment.CenterStart) on the Icon's Modifier parameter to center the icon around the start of the Box Composable. This alignment will have priority over the Box's alignment parameter.
You can also delete the Spacer composable because the Box layout children are stacked one on top of the other in the composition order. So the Spacer composable is basically laying below the Text composable in the center.
If you want some space between the Icon and the Text, you could use some padding around the Icon instead.
Try this (It worked for me) :
Box(modifier = modifier.fillMaxWidth(),
contentAlignment = Alignment.Center) {
Icon(
imageVector = imageVector,
modifier = Modifier
.size(18.dp)
.align(Alignment.CenterStart),
contentDescription = "drawable icons",
tint = Color.Unspecified
)
Text(
text = buttonText,
color = Color.Black,
textAlign = TextAlign.Center
)
}
#Composable
fun GoogleButton(
modifier: Modifier = Modifier,
imageVector: ImageVector,
buttonText: String,
onClick: (isEnabled: Boolean) -> Unit = {},
enable: Boolean = true,
backgroundColor: Color,
fontColor: Color,
) {
Button(
onClick = { onClick(enable) },
modifier = modifier
.fillMaxWidth()
.shadow(0.dp)
.noInteractionClickable(enabled = false) { onClick(enable) },
elevation = ButtonDefaults.elevation(
defaultElevation = 0.dp,
pressedElevation = 0.dp,
hoveredElevation = 0.dp,
focusedElevation = 0.dp
),
shape = RoundedCornerShape(28.dp),
contentPadding = PaddingValues(15.dp),
colors = ButtonDefaults.buttonColors(
backgroundColor = backgroundColor,
contentColor = fontColor
),
border = BorderStroke(1.dp, MaterialTheme.colors.getButtonBorderStroke)
) {
Box(
modifier = Modifier
.fillMaxWidth(),
contentAlignment = Alignment.Center
) {
Row(
modifier = Modifier
.fillMaxWidth()
.align(Alignment.CenterStart)
) {
Spacer(modifier = Modifier.width(4.dp))
Icon(
imageVector = imageVector,
modifier = Modifier
.size(18.dp),
contentDescription = "drawable_icons",
tint = Color.Unspecified
)
}
Text(
modifier = Modifier.align(Alignment.Center),
text = buttonText,
color = MaterialTheme.colors.loginButtonTextColor,
textAlign = TextAlign.Center,
fontSize = 16.sp,
fontFamily = FontFamily(
Font(
R.font.roboto_medium
)
)
)
}
}
}
As suggested in other answers you can wrap the content with a Box.
As alternative you can simply use the RowScope of the Button without any container.
Just apply a weight(1f) modifier to the Text and an offset(x=- iconWidth/2).
Something like:
Button(
//....
) {
Icon(
imageVector = imageVector,
modifier = Modifier.size(iconWidth),
contentDescription = "drawable icons",
tint = Color.Unspecified
)
Text(
text = "Button",
color = Color.Black,
textAlign = TextAlign.Center,
modifier = Modifier
.weight(1f)
.offset(x= -iconWidth/2) //default icon width = 24.dp
)
}
If you want to use a Box, remove the contentAlignment = Alignment.Center in the Box and use:
Box(modifier = Modifier.fillMaxWidth()) {
Icon( /* ..... */ )
Text(
modifier = Modifier.fillMaxWidth(),
text = "buttonText",
textAlign = TextAlign.Center
)
}
Box doesn't provide bounds, so for longer texts, it causes overlapping. Row works better for me. Also, you can use Spacer here which is not possible for Box. In my case, I have used spacedBy as a replacement for Spacer:
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(16.dp),
verticalAlignment = Alignment.CenterVertically
) {
Icon(
painter,
contentDescription = null
)
Box(
modifier = Modifier.weight(1F),
contentAlignment = Alignment.Center
) {
Text(buttonText)
}
}
Box(contentAlignment = Center){
Icon(Modifier.align(CenterStart))
Text()
}
I have tried applying SpaceBetween, SpaceEvenly and SpaceAround but nothing seems to be working here. My main goal here is to put the iconButton and the text on the start and end of the same row. Please don't refer to me appbar for doing so I just want to know why this is not working and what is the fix?
Row(
modifier = Modifier.padding(30.dp),
horizontalArrangement = Arrangement.SpaceBetween
){
Text(
"NOTES",
fontSize = 30.sp,
fontWeight = FontWeight.Bold,
color = Color.White
)
IconButton(onClick = { /*TODO*/ }) {
Icon(
Icons.Filled.Search,
contentDescription = "Search",
tint = Color.LightGray
)
}
}
Add the modifier fillMaxWidth() in your Row
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween
){
//....your content
}
In the Row modifier use fillMaxWidth()
Row(
modifier = Modifier
.fillMaxWidth()
.padding(30.dp),
horizontalArrangement = Arrangement.SpaceBetween
)
I'm new to jetpack compose. I want to start typing from TextField's centervertically-start
position but I can't put "Example" to center
vertically-start position.
Row(
modifier = Modifier
.fillMaxWidth()
.height(50.dp)
.shadow(5.dp)
.background(Color.Yellow),
) {
BasicTextField(
value = text,
onValueChange = {onvalueChange(it)},
modifier = Modifier.weight(10f).background(Color.Blue).fillMaxSize(),
singleLine = true,
textStyle = LocalTextStyle.current.copy(
textAlign = TextAlign.Center
)
)
Image(painter = painterResource(id = R.drawable.ic_baseline_search_24),
contentDescription = "Search",
modifier = Modifier.weight(2f).fillMaxSize()
)
This is my code
And this is what I want to do.
Row has a verticalAlignment for this. Also, if you want your TextField left align like the picture, remove the textAlign (or change it but it default to start)
Row(
modifier = Modifier
.fillMaxWidth()
.height(50.dp)
.shadow(5.dp)
.background(Color.Yellow),
verticalAlignment = Alignment.CenterVertically,
) {
BasicTextField(
value = text,
onValueChange = {onvalueChange(it)},
modifier = Modifier.weight(10f).background(Color.Blue).fillMaxSize(),
singleLine = true,
)
Image(painter = painterResource(id = R.drawable.ic_baseline_search_24),
contentDescription = "Search",
modifier = Modifier.weight(2f).fillMaxSize()
)
}
Use background box to control, please try:
Row(
modifier = Modifier
.fillMaxWidth()
.height(50.dp)
.shadow(5.dp)
.background(Color.Yellow),
) {
Box(Modifier.weight(10f).background(Color.Blue).fillMaxSize(),contentAlignment = CenterStart){
BasicTextField(
value = text,
onValueChange = { onvalueChange(it) },
modifier = Modifier.wrapContentHeight(
Alignment.CenterVertically),
singleLine = true,
textStyle = LocalTextStyle.current.copy(
textAlign = TextAlign.Start
)
)
}
Image(
Icons.Filled.Search,
contentDescription = "Search",
modifier = Modifier.weight(2f).fillMaxSize()
)
}