How to change border width of a particular side only in jetpack compose? - android

I am trying to achieve the below layout
enter image description here
There is no way to set individual border width in jetpack compose
This is my code
Row(
modifier = Modifier
.border(width = 1.dp, shape = RoundedCornerShape(4.dp), color = Purple3)
.padding(10.dp),
verticalAlignment = Alignment.CenterVertically
) {
Image(
painter = painterResource(id = R.drawable.info),
contentDescription = stringResource(id = R.string.long_press_an_item),
)
Text(
text = stringResource(id = R.string.long_press_an_item),
fontFamily = FontFamily(Font(R.font.inter_medium)),
fontSize = 12.sp,
color = Gray5,
modifier = Modifier.padding(horizontal = 10.dp)
)
}

I used different colors, but you can see the result:
I see there three ways, how you can achieve this effect:
You can create custom modifier extension method, as I did in one my project, using drawBehind Modifier:
#Preview
#Composable
fun Preview() {
Row(
modifier = Modifier
.someCustomOutline(
outlineColor = MaterialTheme.colors.primary,
surfaceColor = MaterialTheme.colors.surface,
startOffset = 3.dp,
outlineWidth = 1.dp,
radius = 4.dp
)
.padding(10.dp),
verticalAlignment = Alignment.CenterVertically
) {
Image(
imageVector = Icons.Default.Info,
contentDescription = null,
)
Text(
text = "long_press_an_item",
fontSize = 12.sp,
modifier = Modifier.padding(horizontal = 10.dp)
)
}
}
#Composable
fun Modifier.someCustomOutline(
outlineColor: Color,
surfaceColor: Color,
startOffset: Dp,
outlineWidth: Dp,
radius: Dp = 1.dp
) = drawBehind {
val startOffsetPx = startOffset.toPx()
val outlineWidthPx = outlineWidth.toPx()
val radiusPx = radius.toPx()
drawRoundRect(
color = outlineColor,
topLeft = Offset(0f, 0f),
size = size,
cornerRadius = CornerRadius(radiusPx, radiusPx),
style = Fill
)
drawRoundRect(
color = surfaceColor,
topLeft = Offset(startOffsetPx, outlineWidthPx),
size = Size(size.width - startOffsetPx - outlineWidthPx, size.height - outlineWidthPx * 2),
cornerRadius = CornerRadius(radiusPx - outlineWidthPx, radiusPx - outlineWidthPx),
style = Fill
)
}
Usage:
this is very bad approach, but I will mention it for just in case
You can just frap your element with Box and add padding to it:
Box(
modifier = Modifier
.background(shape = RoundedCornerShape(4.dp), color = Purple3)
.padding(start = 3.dp, top = 1.dp, end = 1.dp, bottom = 1.dp)
) {
Row(
modifier = Modifier
.background(MaterialTheme.colors.surface, shape = RoundedCornerShape(3.dp))
.padding(10.dp),
verticalAlignment = Alignment.CenterVertically
) {
Image(
imageVector = painterResource(id = R.drawable.info),
contentDescription = stringResource(id = R.string.long_press_an_item),
)
Text(
text = stringResource(id = R.string.long_press_an_item),
fontSize = 12.sp,
fontFamily = FontFamily(Font(R.font.inter_medium)),
color = Gray5,
modifier = Modifier.padding(horizontal = 10.dp)
)
}
}

This can be done using a Box with background as your border and adding padding more padding to start than other corners
#Preview
#Composable
private fun Test() {
Box(modifier = Modifier.background(Color(0xffBA68C8), RoundedCornerShape(4.dp))) {
Row(
modifier = Modifier
.padding(start = 4.dp, top = 1.dp, bottom = 1.dp, end = 1.dp)
.background(Color.White, RoundedCornerShape(4.dp))
.padding(10.dp),
verticalAlignment = Alignment.CenterVertically
) {
Image(
imageVector = Icons.Default.Info,
contentDescription = "Long press item to enable multi-select and bulk operations"
)
Text(
text = "Long Press on Item",
fontSize = 12.sp,
color = Color.Gray,
modifier = Modifier.padding(horizontal = 10.dp)
)
}
}
}

Container(
decoration: BoxDecoration(
gradient: LinearGradient(stops: const [
0.014,
0.014
], colors: [
isError ? redColor : greenColor,
Theme.of(context).colorScheme.background
]),
color: Theme.of(context).colorScheme.background,
borderRadius: BorderRadius.circular(10),
border: Border.all(color: isError ? redColor : greenColor, width: 1),
),
padding: const EdgeInsets.symmetric(
vertical: 12,
horizontal: 12,
),
child: Row(
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: Text(
text,
style: GoogleFonts.inter(
fontWeight: FontWeight.w500,
fontSize: 12,
color: gray6Color,
),
),
)
],
)

Related

Aligning the text of a TextField with its Trailing icon

I have an svg icon in my drawables folder from our designer, and I'm trying to figure out a way to align the trailing icon of the TextField with its text in a way that it will look the same on most devices. I'm trying to avoid fixed dp values but I can't find a built-in way to do this.
screen code:
var customAmountTxt by remember { mutableStateOf(TextFieldValue()) }
TextField(
value = customAmountTxt,
onValueChange = {
customAmountTxt = it
},
maxLines = 1,
singleLine = true,
leadingIcon = {
Icon(
painter = painterResource(id = R.drawable.ic_euro),
contentDescription = stringResource(
R.string.euro_icon_desc
),
modifier = Modifier.padding(
start = 16.dp,
end = 16.dp,
top = 12.dp,
bottom = 12.dp
)
)
},
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Number,
imeAction = ImeAction.Done
),
keyboardActions = KeyboardActions(onDone = {
focusManager.clearFocus()
keyboardController?.hide()
}),
shape = RoundedCornerShape(6.dp),
colors = TextFieldDefaults.textFieldColors(
backgroundColor = colorResource(id = R.color.white),
textColor = colorResource(id = R.color.black),
focusedIndicatorColor = colorResource(id = R.color.white),
unfocusedIndicatorColor = colorResource(id = R.color.white),
disabledIndicatorColor = colorResource(id = R.color.white),
cursorColor = colorResource(id = R.color.black)
),
textStyle = TextStyle(
color = Color.Black,
fontSize = 16.sp,
fontWeight = FontWeight.Normal,
textAlign = TextAlign.Start
),
modifier = Modifier
.height(50.dp)
.fillMaxWidth()
.shadow(8.dp, shape = RoundedCornerShape(6.dp))
)
current output:

How to align leadingIcon in OutlinedTextField of jetpack compose with the value/placeholder

I am new to jetpack compose, I want my app to load the Exo two light font so I override the material typography like this,
val exoTwoLight = FontFamily(
Font(R.font.exo_two_light),
Font(R.font.exo_two_light, FontWeight.Bold)
)
val exoTwoLightTypography = Typography(
h1 = TextStyle(
fontFamily = exoTwoLight,
fontWeight = FontWeight.Bold,
fontSize = 96.sp
),
h2 = TextStyle(
fontFamily = exoTwoLight,
fontWeight = FontWeight.Bold,
fontSize = 60.sp
),
h3 = TextStyle(
fontFamily = exoTwoLight,
fontWeight = FontWeight.Bold,
fontSize = 48.sp
),
h4 = TextStyle(
fontFamily = exoTwoLight,
fontWeight = FontWeight.Bold,
fontSize = 34.sp
),
h5 = TextStyle(
fontFamily = exoTwoLight,
fontWeight = FontWeight.Bold,
fontSize = 20.sp
),
h6 = TextStyle(
fontFamily = exoTwoLight,
fontWeight = FontWeight.Bold,
fontSize = 12.sp
),
subtitle1 = TextStyle(
fontFamily = exoTwoLight,
fontWeight = FontWeight.Normal,
fontSize = 16.sp
),
subtitle2 = TextStyle(
fontFamily = exoTwoLight,
fontWeight = FontWeight.Medium,
fontSize = 14.sp
),
body1 = TextStyle(
fontFamily = exoTwoLight,
fontWeight = FontWeight.Normal,
fontSize = 16.sp
),
body2 = TextStyle(
fontFamily = exoTwoLight,
fontWeight = FontWeight.Normal,
fontSize = 14.sp
),
button = TextStyle(
fontFamily = exoTwoLight,
fontWeight = FontWeight.Medium,
fontSize = 14.sp,
),
caption = TextStyle(
fontFamily = exoTwoLight,
fontWeight = FontWeight.Normal,
fontSize = 12.sp,
),
overline = TextStyle(
fontFamily = exoTwoLight,
fontWeight = FontWeight.Normal,
fontSize = 10.sp,
)
)
Now when I try to load an input field in the app I can see that placeholder and leading icons are not aligned at all
I tried to customize the placeholder as it is required as a composable
By customization, I mean adding top padding of 2/4 dp to the placeholder
Row(modifier = Modifier.padding(top=10.dp)) {
OutlinedTextField(
leadingIcon = {
Icon(
painter = painterResource(id = R.drawable.gallery_icon),
contentDescription = "",
tint = colorResource(R.color.teal_200),
modifier = Modifier.clickable {
}
)
},
placeholder = {
Text(
text = "Placeholder",
style = MaterialTheme.typography.button,
modifier = Modifier.padding(top = 3.dp)
)
},
modifier = Modifier.fillMaxWidth(),
readOnly = false,
value = sampleValue,
onValueChange = {
sampleValue = it
},
maxLines = 1,
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next),
)
}
It only solves the issue for the placeholder but values seem to be misaligned
This is the complete code
var sampleValue by remember {
mutableStateOf("")
}
Column{
Row(modifier = Modifier.padding(top=10.dp)){
OutlinedTextField(
leadingIcon = {
if (true) {
Icon(
painter = painterResource(id = R.drawable.capture_more_images),
contentDescription = "",
tint = colorResource(R.color.teal_200),
modifier = Modifier.clickable {
}
)
} else {
Icon(
painter = painterResource(id = R.drawable.capture_more_images),
contentDescription = "",
tint = colorResource(R.color.disabled)
)
}
},
placeholder = {
Row(
modifier = Modifier.height(24.dp),
verticalAlignment = Alignment.CenterVertically
){
Text(
text = "Placeholder",
style = MaterialTheme.typography.button
)
}
},
modifier = Modifier.fillMaxWidth(),
readOnly = false,
value = sampleValue,
onValueChange = {
sampleValue = it
},
maxLines = 1,
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next),
)
}
Row(modifier = Modifier.padding(top=10.dp)) {
OutlinedTextField(
leadingIcon = {
Icon(
painter = painterResource(id = R.drawable.gallery_icon),
contentDescription = "",
tint = colorResource(R.color.teal_200),
modifier = Modifier.clickable {
}
)
},
placeholder = {
Text(
text = "Placeholder",
style = MaterialTheme.typography.button,
modifier = Modifier.padding(top = 3.dp)
)
},
modifier = Modifier.fillMaxWidth(),
readOnly = false,
value = sampleValue,
onValueChange = {
sampleValue = it
},
maxLines = 1,
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next),
)
}
Row(modifier = Modifier.padding(top=10.dp)) {
OutlinedTextField(
placeholder = {
Text(
text = "Placeholder",
style = MaterialTheme.typography.button,
)
},
modifier = Modifier.fillMaxWidth(),
value = sampleValue,
onValueChange = {
sampleValue = it
}
)
}
}
I want that placeholder to be aligned vertically centered ( without giving any top padding ) with the leading icon what is the solution?
The solution to this is to set the singleLine property of the TextField to true. Like this:
TextField(
singleLine = true,
placeholder = {
Text(text = "Search for reminders")
},
leadingIcon = {
Icon(
painter = painterResource(id = R.drawable.search_icon),
tint = MaterialTheme.colorScheme.outline,
contentDescription = "Back button"
)
}
)
Many icons have built-in padding on one or more sides. To compensate for this, you can adjust the icon's position using the offset modifier. Set it some positive or negative value:
placeholder = {
Row(
modifier = Modifier.height(24.dp).offset(y = 5.dp),
verticalAlignment = Alignment.CenterVertically
){
Text(
text = "Placeholder",
style = MaterialTheme.typography.button
)
}
}

Align text to right in button in Jetpack compose

I have button with text:
Button(
colors = ButtonDefaults.buttonColors(
backgroundColor = Color.Transparent,
contentColor = colors.primary,
),
elevation = null,
onClick = {},
border = BorderStroke(0.dp, Color.Transparent),
) {
Text(
text = stringResource(id = R.string.name),
fontSize = 12.sp,
textAlign = TextAlign.Right
)
}
Now text in button is centered. How can I move this text to right/end in this button. textAlign = TextAlign.Right not working.
You have to specify width for Button and Text.
Button(
colors = ButtonDefaults.buttonColors(
backgroundColor = Color.Transparent,
contentColor = colors.primary,
),
elevation = null,
onClick = {},
border = BorderStroke(0.dp, Color.Transparent),
modifier = Modifier.fillMaxWidth()
) {
Text(
text = stringResource(id = R.string.name),
fontSize = 12.sp,
textAlign = TextAlign.Right,
modifier = Modifier.fillMaxWidth(),
)
}
I have given full width for Button
modifier = Modifier.fillMaxWidth()
Also let your Text to occupy that parent width.
modifier = Modifier.fillMaxWidth()

Jetpack Compose: Center Icon or Trailing elements in a ListItem

I'm trying to center the icon and trailing elements vertically using a ListItem. I'm not sure if it is possible or I need to drop the ListItem and use a combination of column/row instead.
I'm using something like:
ListItem(
Modifier.clickable(onClick = onClick),
icon = {
Box(
modifier = Modifier.fillMaxHeight(), contentAlignment = ALignment.Center
) {
Text(
text = dateUtil.formatTime(item.startTime),
style = TextStyle(
color = SnyDarkBlue,
fontSize = 14.sp,
fontFamily = oswaldFamily,
fontWeight = FontWeight.Bold,
letterSpacing = (-0.25).sp,
),
)
}
},
thanks in advance!
You can center both the icon and text sections using a Column:
ListItem(
modifier = Modifier
.fillMaxWidth()
.requiredHeight(50.dp)
.background(color = Color.Gray),
icon = {
Column(
modifier = Modifier
.fillMaxHeight(), verticalArrangement = Arrangement.Center
) {
Text(
text = "06:00 PM"
)
}
},
text = {
Column(
modifier = Modifier
.fillMaxHeight(), verticalArrangement = Arrangement.Center
) {
Text("Your item text goes here")
}
},
)

Icons getting disappears if the text is too long in Jetpack Compose

#Composable
fun TopAppBar(
name: String,
modifier: Modifier = Modifier
) {
Row(
modifier = modifier
.fillMaxWidth()
.padding(20.dp, 0.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween
) {
Icon(
imageVector = Icons.Default.ArrowBack,
contentDescription = "Back",
tint = Color.Black,
modifier = Modifier.size(24.dp)
)
Text(
text = name,
overflow = TextOverflow.Ellipsis,
fontWeight = FontWeight.Bold,
fontSize = 20.sp,
maxLines = 1
)
Row {
Icon(
painter = painterResource(id = R.drawable.ic_bell),
contentDescription = null,
tint = Color.Black,
modifier = Modifier
.padding(8.dp, 8.dp)
.size(24.dp)
)
Icon(
painter = painterResource(id = R.drawable.ic_dotmenu),
contentDescription = null,
tint = Color.Black,
modifier = Modifier
.padding(8.dp, 8.dp)
.size(24.dp)
)
}
}
}
You have to set the weight and the fill to false:
Text(
modifier = Modifier.weight(weight = 1f, fill = false),
text = name,
overflow = TextOverflow.Ellipsis,
fontWeight = FontWeight.Bold,
fontSize = 20.sp,
maxLines = 1
)
You can add the weight modifier to the Text composable
Row(){
Icon()
Text(
text = ".....",
overflow = TextOverflow.Ellipsis,
fontWeight = FontWeight.Bold,
fontSize = 20.sp,
maxLines = 1,
modifier = Modifier.weight(1f)
)
//...
}
.

Categories

Resources