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"
)
}
}
Related
enter image description here
i still confused using component view in jetpack compose,
please help me for making this one. thanks
i was tried but it's not like current view in figma
Card(modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 20.dp)
.wrapContentHeight(), elevation = 8.dp,
shape = RoundedCornerShape(25.dp)
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 4.dp)
.wrapContentHeight(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween
) {
Image(painter = painterResource(id = R.drawable.ic_points_star_icon), modifier = Modifier
.padding(vertical = 8.dp)
.size(60.dp), contentDescription = "")
Column(modifier = Modifier
.weight(1f)
.padding(vertical = 8.dp), horizontalAlignment = Alignment.Start) {
Text(text = "Heading Text", style = AppTheme.typography.boldHeaderStyle)
Text(text = "This is sample body text", color = textColor.copy(0.4f), style = AppTheme.typography.captionTextStyle)
}
Button(
onClick = { /*Your on Click*/ },
shape = RoundedCornerShape(5.dp),
elevation = ButtonDefaults.elevation(
defaultElevation = 0.dp,
pressedElevation = 0.dp,
disabledElevation = 0.dp,
hoveredElevation = 0.dp,
focusedElevation = 0.dp,
),
colors = ButtonDefaults.buttonColors(
backgroundColor = BackArrowTint.copy(0.6f),
contentColor = Color.White
),
modifier = Modifier
.wrapContentHeight()
.padding(horizontal = 4.dp),
) {
Text(
text = "Buy Ticket",
modifier = Modifier.padding(vertical = 2.dp, horizontal = 4.dp),
color = White,
style = AppTheme.typography.buttonStyle,
)
}
}
}
Sample Image:
I want to display the icons below so the center one is overlapping.
I am trying to use the Box but not sure how to arrange them so they are overlapping and in the center of the screen.
I have started using a Box with 3 Box stacked on each other. But not sure about how to arrange them so the center slightly overlaps the left and right icons. And slightly higher.
fun SurveyIconScreen() {
Box {
Box(modifier = Modifier
.clip(CircleShape)
.size(22.dp)
.background(color = Color.White),
contentAlignment = Alignment.Center) {
Icon(painter = painterResource(id = R.drawable.ic_star), contentDescription = "Star")
}
Box(modifier = Modifier
.clip(CircleShape)
.size(22.dp)
.background(color = Color.White),
contentAlignment = Alignment.Center) {
Icon(painter = painterResource(id = R.drawable.ic_cart), contentDescription = "Star")
}
Box(modifier = Modifier
.clip(CircleShape)
.size(22.dp)
.background(color = Color.White),
contentAlignment = Alignment.Center) {
Icon(painter = painterResource(id = R.drawable.ic_cart), contentDescription = "Star")
}
}
}
You can apply an offset modifier to overlap the icons.
Also use the zIndex(1f) modifier to drawn the icon in the center on top of all other icons.
Something like:
val shape = RoundedCornerShape(4.dp)
val borderColor = LightGray
Row(
modifier = Modifier.fillMaxWidth().height(70.dp),
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically
){
Icon(Icons.Outlined.Star, contentDescription = "Star",
modifier = Modifier
.offset(x = 3.dp)
.size(32.dp)
.border(BorderStroke(1.dp,borderColor), shape)
.background(White)
)
Icon(
Icons.Outlined.ShoppingCart,
contentDescription = "Star",
modifier = Modifier
.zIndex(1f)
.offset(y = -12.dp)
.size(32.dp)
.border(BorderStroke(1.dp,borderColor), shape)
.background(White)
)
Icon(Icons.Outlined.Note, contentDescription = "Star",
modifier = Modifier
.offset(x = -3.dp)
.size(32.dp)
.border(BorderStroke(1.dp,borderColor), shape)
.background(White)
)
}
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")
}
Can not understand why in this card, in the column, the spacebetween vertical alignment is not taking into account. I'm expecting the Title to be on top, and the "View Details" button to be at the bottom of the Column
fun UserCard(image:Int, text:String, actionButtonLabel:String){
Card(
elevation = 4.dp,
modifier = Modifier
.padding(12.dp)
.fillMaxWidth()
.wrapContentHeight()
) {
Row(
horizontalArrangement = Arrangement.SpaceBetween,
modifier = Modifier
.padding(8.dp)
.border(width = 1.dp, color = Color.Blue)
.padding(12.dp)
) {
Image(
painter = painterResource(id = image),
contentDescription = "",
contentScale = ContentScale.Crop,
modifier = Modifier
.size(120.dp)
.clip(CircleShape)
)
Column(
modifier= Modifier.fillMaxHeight(),
horizontalAlignment = Alignment.End,
verticalArrangement = Arrangement.SpaceBetween, // <-- seems not to be taking into account
) {
Title(text)
Button(onClick = { }) {
Text(text = actionButtonLabel)
}
}
}
}
}
example of call of UserCard
UserCard(
image= R.drawable.iron,
text = "Live after death",
actionButtonLabel = "View details"
)
You can apply an intrinsic measurements to the Row container and the fillMaxHeight() Modifier to the Column.
Your issue is the height of the column.
Row(
horizontalArrangement = Arrangement.SpaceBetween,
modifier = Modifier.height(IntrinsicSize.Min)
//..
){
/* Image */
Column(
modifier = Modifier
.fillMaxHeight(),
horizontalAlignment = Alignment.End,
verticalArrangement = Arrangement.SpaceBetween){
//...
}
}
I'm trying to use the new Jetpack Compose UI framework, but I'm running into an issue. I'd like to achieve this layout, which in xml is pretty easy to achieve:
But I can't figure out how to make the vertical divider take up the available vertical space, without specifying a fixed height. This code that I've tried doesn't seem to work:
#Composable
fun ListItem(item: PlateUI.Plate) {
Surface(
modifier = Modifier.fillMaxWidth(),
shape = RoundedCornerShape(8.dp),
elevation = 2.dp
) {
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically
) {
Column(
modifier = Modifier
.padding(8.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(text = "Code")
Text(text = item.code)
}
Spacer(
modifier = Modifier
.preferredWidth(1.dp)
.background(color = MaterialTheme.colors.onSurface.copy(0.12f))
)
Spacer(modifier = Modifier.weight(1f))
Text(
modifier = Modifier
.padding(horizontal = 8.dp, vertical = 34.dp),
text = item.name
)
Spacer(modifier = Modifier.weight(1f))
}
}
}
I keep getting this result:
I also tried with ConstraintLayout, but it still didn't work
#Composable
fun ListItem(item: PlateUI.Plate) {
Surface(
modifier = Modifier.fillMaxWidth(),
shape = RoundedCornerShape(8.dp),
elevation = 2.dp
) {
ConstraintLayout(
modifier = Modifier.fillMaxWidth(),
) {
val(column, divider, text) = createRefs()
Column(
modifier = Modifier
.padding(8.dp)
.constrainAs(column){
top.linkTo(parent.top)
bottom.linkTo(parent.bottom)
start.linkTo(parent.start)
},
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(text = "Code")
Text(text = item.code)
}
Spacer(
modifier = Modifier
.preferredWidth(1.dp)
.background(color = MaterialTheme.colors.onSurface.copy(0.12f))
.constrainAs(divider){
top.linkTo(parent.top)
bottom.linkTo(parent.bottom)
start.linkTo(column.end)
}
)
Text(
modifier = Modifier
.padding(horizontal = 8.dp, vertical = 34.dp)
.constrainAs(text){
start.linkTo(divider.end)
end.linkTo(parent.end)
top.linkTo(parent.top)
bottom.linkTo(parent.bottom)
},
text = item.name
)
}
}
}
But nothing seems to work. Is this a bug, a missing feature or am I just missing something?
EDIT: Apparently the real problem is that the divider doesn't know how to measure when the Surface doesn't have a fixed height, setting height equal to some number solves the issue, but then the view doesn't adapt to the content height anymore, so this can't be the solution
You can apply:
the modifier .height(IntrinsicSize.Max) to the Row
the modifiers .width(1.dp).fillMaxHeight() to the Spacer
You can read more about the Intrinsic measurements here.
Something like:
Row(
modifier = Modifier.fillMaxWidth().height(IntrinsicSize.Max),
verticalAlignment = Alignment.CenterVertically
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
....
) {
Text(text = "....")
}
Spacer(
modifier = Modifier
.width(1.dp)
.fillMaxHeight()
.background(color = MaterialTheme.colors.onSurface.copy(0.12f))
)
Text(...)
}
You can set Intrinsic.Max for the preferredHeight of the Row, then set the Spacer to fill max height. You can read more on Intrinsics in this codelab section.
#Composable
fun ListItem() {
Surface(
modifier = Modifier.fillMaxWidth(),
shape = RoundedCornerShape(8.dp),
elevation = 2.dp
) {
Row(
modifier = Modifier.fillMaxWidth().preferredHeight(IntrinsicSize.Max),
verticalAlignment = Alignment.CenterVertically
) {
Column(
modifier = Modifier
.padding(8.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(text = "Code")
Text(text = "2456")
}
Spacer(
modifier = Modifier
.preferredWidth(1.dp)
.fillMaxHeight()
.background(color = Color.Black.copy(0.12f))
)
Spacer(modifier = Modifier.weight(1f))
Text(
modifier = Modifier
.padding(horizontal = 8.dp, vertical = 34.dp),
text = "Some name"
)
Spacer(modifier = Modifier.weight(1f))
}
}
}
I've solved it using constraint layout:
Box(modifier = Modifier.padding(Dp(50f))) {
ConstraintLayout(
modifier = Modifier
.border(width = Dp(1f), color = Color.Black)
.fillMaxWidth()
) {
val (left, divider, right) = createRefs()
Column(
modifier = Modifier
.padding(horizontal = Dp(20f))
.constrainAs(left) {
width = Dimension.wrapContent
start.linkTo(parent.start)
top.linkTo(parent.top)
end.linkTo(divider.start)
bottom.linkTo(parent.bottom)
}
) {
Text(text = "Code")
Text(text = "A12")
}
Box(
modifier = Modifier
.width(Dp(1f))
.background(Color.Black)
.constrainAs(divider) {
width = Dimension.wrapContent
height = Dimension.fillToConstraints
start.linkTo(left.end)
top.linkTo(parent.top)
end.linkTo(right.start)
bottom.linkTo(parent.bottom)
}
)
Box(
modifier = Modifier
.constrainAs(right) {
width = Dimension.fillToConstraints
start.linkTo(divider.end)
top.linkTo(parent.top)
end.linkTo(parent.end)
bottom.linkTo(parent.bottom)
}
) {
Text(
text = "Test",
modifier = Modifier
.padding(vertical = Dp(100f))
.align(Alignment.Center)
)
}
}
}
The key part is using that modifier height = Dimension.fillToConstraints
There are plenty of solutions here, but I thought I could demonstrate the ConstraintLayout approach and add a helpful usage of the IntrinsicSize enum that solves one of the issues (needing an adaptive height for the composable). Interestingly, either IntrinsicSize.Max or IntrinsicSize.Min will yield the desired behavior.
I used most of your code. The key differences are:
declares a guideline (my value passed in for the fraction does not produce the exact result you were looking for, but can be adjusted easily (use a fraction slightly smaller than .2) This can be useful if you expect wrapContent to alter your left Text to vary the location of a spacer, but would prefer a consistent spacer location across a list of these items.
others have mentioned, spacer modifier should include .fillMaxHeight()
define the height of the surface wrapper to be .height(IntrinsicSize.Min) docs ref here: https://developer.android.com/jetpack/compose/layout#intrinsic-measurements
divider start is constrained to the guideline
had to change the Spacer modifier to access the width, instead of preferredWidth
#Composable
fun ListItem(item: Plate) {
Surface(
modifier = Modifier.fillMaxWidth().height(IntrinsicSize.Min),
shape = RoundedCornerShape(8.dp),
elevation = 2.dp
) {
ConstraintLayout(
modifier = Modifier.fillMaxWidth(),
) {
val guideline = createGuidelineFromStart(0.2f)
val(column, divider, text) = createRefs()
Column(
modifier = Modifier
.padding(8.dp)
.constrainAs(column){
top.linkTo(parent.top)
bottom.linkTo(parent.bottom)
start.linkTo(parent.start)
end.linkTo(guideline)
},
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(text = "Code")
Text(text = item.code)
}
Spacer(
modifier = Modifier
.constrainAs(divider){
top.linkTo(column.top)
bottom.linkTo(column.bottom)
start.linkTo(guideline)
}
.width(1.dp)
.fillMaxHeight()
.background(color = MaterialTheme.colors.onSurface.copy(0.12f))
)
Text(
modifier = Modifier
.padding(horizontal = 8.dp, vertical = 34.dp)
.constrainAs(text){
start.linkTo(divider.end)
end.linkTo(parent.end)
top.linkTo(parent.top)
bottom.linkTo(parent.bottom)
},
text = item.name
)
}
}
}
I think Row layout is enough.
#Preview(showBackground = true, heightDp = 100)
#Composable
fun ListItem(item: PlateUI.Plate = PlateUI.Plate()) {
Card(
shape = RoundedCornerShape(8.dp)
) {
Row(
modifier = Modifier
.fillMaxSize(),
verticalAlignment = Alignment.CenterVertically
) {
Text(
modifier = Modifier.padding(8.dp),
text = "Code\n${item.code}",
textAlign = TextAlign.Center
)
Box(
Modifier
.fillMaxHeight()
.width(1.dp)
.background(color = MaterialTheme.colors.onSurface.copy(0.12f))
)
Text(
modifier = Modifier
.weight(1f)
.padding(8.dp),
text = item.name,
textAlign = TextAlign.Center
)
}
}
}