I'm using BasicTextField to stylize my text input field. I'm having a problem where when I focus on said text input on the lower part of the screen, keyboard overlaps my input a bit. Is there a way to fix it ? Here's my BasicTextField
Row(
modifier = Modifier
.fillMaxWidth()
.heightIn(min = 68.dp)
.border(width = 1.dp, color = Color.Blue)
.background(color = Color.White),
verticalAlignment = Alignment.Top
) {
BasicTextField(
modifier = Modifier
.offset(y = (8).dp)
.padding(start = 16.dp, top = 20.dp, bottom = 16.dp)
.weight(1f),
textStyle = TextStyle(fontSize = 24.sp, lineHeight = 37.sp),
maxLines = 5,
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
value = input,
onValueChange = {
input = it
},
decorationBox = {
Text(
modifier = Modifier.offset(y = (-16).dp),
text = "amount",
fontSize = 12.sp,
color = Color.Gray,
fontWeight = FontWeight.Bold
)
it()
},
)
Row(modifier = Modifier.align(Alignment.CenterVertically)) {
Image(
modifier = Modifier.padding(start = 4.dp, end = 16.dp),
painter = painterResource(id = R.drawable.arrow_down),
contentDescription = null,
colorFilter = ColorFilter.tint(color = Color.Blue)
)
}
}
I tried adding specific height on BasicTextField, removing border and background from Row and adding to BasicTextField, but end result wasn't the text field looking like I want it to. I also need the text field to be able to expand on break line and that's where a lot of times it went bad when trying to adjust it. Maybe I'm missing something.
Related
Quick question here:
Is this a bug inside jetpack compose TextField or am I missing something:
#Composable
fun TextFieldWithPlaceholder() {
val text = rememberSaveable {
mutableStateOf("")
}
Box(modifier = Modifier
.fillMaxSize()
.background(MaterialTheme.colors.background)) {
TextField(
modifier = Modifier
.background(Color.Blue)
.size(width = 300.dp, height = 50.dp),
value = text.value,
onValueChange = { value ->
text.value = value
},
singleLine = true,
colors = TextFieldDefaults.textFieldColors(
backgroundColor = Color.Transparent,
focusedIndicatorColor = Color.Transparent,
unfocusedIndicatorColor = Color.Transparent,
focusedLabelColor = Color.Transparent,
unfocusedLabelColor = Color.Transparent,
placeholderColor = Color.Red,
cursorColor = Color.White
),
placeholder = {
Text(
modifier = Modifier.fillMaxWidth(),
textAlign = TextAlign.Center,
text = "Placeholder"
)
},
textStyle = MaterialTheme.typography.body2.copy(textAlign = TextAlign.Center)
)
}
}
If you build the project with this composable, and tap inside the input field, you'll notice that the cursor is behind the placeholder text (talking about the Z axis). Parts of the cursor are not visible due to "Placeholder" text being on top of it.
Is there a way to force it to be on top of placeholder?
Thanks in advance
Unable to reduce the huge padding in OutlinedButton. Tried contentPadding, modifier padding, etc. Cannot reduce padding for text "apple". Any idea? Should I use any other type of compose component for this?
OutlinedButton(
onClick = {},
border = BorderStroke(1.dp, Color.White),
shape = RoundedCornerShape(12.dp),
contentPadding = PaddingValues(0.dp),
modifier = Modifier
.background(bgColor)
.height(24.dp)
.padding(all = 0.dp),
colors = ButtonDefaults.outlinedButtonColors(backgroundColor = bgColor)) {
Text("apple",
color = Color.White,
style = MaterialTheme.typography.body2,
modifier = Modifier.height(10.dp).padding(vertical = 0.dp), //.background(bgColor),
)
}
Updated after #liveAnyway's answer (thanks!) which appeared to help. After that I removed height from OutlinedButton too - ideally I wanted it like "wrap-content". Once I made that change, I still see the padding. Bottomline I don't want any absolute height specified so that it can work with different font size from system settings.
Row(modifier = Modifier.padding(vertical = 12.dp)) {
OutlinedButton(
onClick = {},
border = BorderStroke(1.dp, Color.White),
shape = RoundedCornerShape(18.dp),
contentPadding = PaddingValues(0.dp),
modifier = Modifier
.background(bgColor)
.padding(all = 0.dp),
colors = ButtonDefaults.outlinedButtonColors(backgroundColor = bgColor)
) {
Text("apple",
color = Color.White,
style = MaterialTheme.typography.body2,
modifier = Modifier.padding(vertical = 0.dp),
)
}
}
Button has default min size modifier. This is done according to Material guidelines, so that the button is easy to hit. If the control size is too small, the user may have problems hitting it, take this into account when changing this parameter.
You can override it by applying defaultMinSize modifier. The 0.dp will be ignored, but starting from 1.dp you will get the desired result:
OutlinedButton(
onClick = { /*TODO*/ },
contentPadding = PaddingValues(),
modifier = Modifier
.defaultMinSize(minWidth = 1.dp, minHeight = 1.dp)
) {
Text(
"Apple",
)
}
Alternatively, you can design your own button without these restrictions:
Surface(
onClick = {
},
shape = MaterialTheme.shapes.small,
color = bgColor,
contentColor = MaterialTheme.colors.primary,
border = ButtonDefaults.outlinedBorder,
role = Role.Button,
) {
Text(
"Apple",
)
}
You have to change the minHeight (default size are MinWidth = 64.dp and MinHeight = 36.dp) and remove the contentPadding with contentPadding = PaddingValues(0.dp):
OutlinedButton(
onClick = {},
border = BorderStroke(1.dp, Color.White),
shape = RoundedCornerShape(12.dp),
contentPadding = PaddingValues(0.dp),
modifier = Modifier.defaultMinSize(
minWidth = ButtonDefaults.MinWidth,
minHeight = 10.dp
)
) {
Text(
"apple",
style = MaterialTheme.typography.body2
)
}
I have two layers in my Compose layout: One for the actual content and the one above is a Box-wrapped OutlinedTextField for search queries.
Here's the sample code:
// Placeholder for layout content
Box(modifier = Modifier.fillMaxSize()) {
Text(
text = stringResource(id = R.string.lorem_ipsum),
color = Color.Gray
)
}
// Overlaying Box with OutlinedTextField
Box(modifier = Modifier
.padding(start = 16.dp, end = 16.dp, bottom = 16.dp, top = 64.dp)
) {
OutlinedTextField(
value = viewModel.query.value,
onValueChange = { viewModel.updateQuery(it) },
modifier = Modifier
.fillMaxWidth()
.align(Alignment.BottomCenter)
.navigationBarsWithImePadding(),
keyboardOptions = KeyboardOptions(
capitalization = KeyboardCapitalization.Characters,
autoCorrect = false,
keyboardType = KeyboardType.Text,
imeAction = ImeAction.None
),
shape = CircleShape,
colors = TextFieldDefaults.textFieldColors(
backgroundColor = Color.White
),
placeholder = { Text(stringResource(id = R.string.search_input_placeholder)) },
maxLines = 1,
singleLine = true
)
}
Even though I'm setting
colors = TextFieldDefaults.textFieldColors(
backgroundColor = Color.White
)
in the OutlinedTextField, the background stays transparent as you can see in the following screenshot:
Adding a background color on the OutlinedTextField's modifier is giving the whole row a rectangled background, which is also not the desired result.
The OutlinedTextField with it's CircleShape should only have a background inside of the shape. How can I achieve that?
I'm using Jetpack Compose version 1.0.4.
Reason
Unfortunately, in version 1.0.4, OutlinedTextField ignores the backgroundColor even if you specify it, so you can remove the colors parameter.
Support for it will be added in 1.1.0:
https://android-review.googlesource.com/c/platform/frameworks/support/+/1741240
It's already present in 1.1.0-alpha06 so you can play with it if you want. Your original code should produce desired outcome on that version.
Solution
To achieve what you want (before 1.1.0 is released) you can simply add a background modifier with the same shape:
.background(Color.White, CircleShape)
Since the order of modifiers is important, you should add it after you apply all the paddings (navigationBarsWithImePadding in your case). Like that:
modifier = Modifier
.fillMaxWidth()
.align(Alignment.BottomCenter)
.navigationBarsWithImePadding()
.background(Color.White, CircleShape),
Note: Also be aware that you cannot use the label parameter with this approach, because the TextField with label will be higher than just the outline shape and these two shaped wouldn't match in size anymore.
Result
Entire code:
// Placeholder for layout content
Box(modifier = Modifier.fillMaxSize()) {
Text(
text = stringResource(id = R.string.lorem_ipsum),
color = Color.Gray
)
}
// Overlaying Box with OutlinedTextField
Box(modifier = Modifier
.padding(start = 16.dp, end = 16.dp, bottom = 16.dp, top = 64.dp)
) {
OutlinedTextField(
value = viewModel.query.value,
onValueChange = { viewModel.updateQuery(it) },
modifier = Modifier
.fillMaxWidth()
.align(Alignment.BottomCenter)
.navigationBarsWithImePadding()
.background(Color.White, CircleShape),
keyboardOptions = KeyboardOptions(
capitalization = KeyboardCapitalization.Characters,
autoCorrect = false,
keyboardType = KeyboardType.Text,
imeAction = ImeAction.None
),
shape = CircleShape,
placeholder = { Text(stringResource(id = R.string.search_input_placeholder)) },
maxLines = 1,
singleLine = true
)
}
How the final result looks like:
I'm new in jetpack compose and I'm trying to do a simple thing that I can't achieve it.
That I want to do is in the same row align one component, in this case a surface, at the start and the other one, the column, at the end of the row.
How can get this?
I'm trying this but it doesn't work:
Row(Modifier.padding(top = 24.dp)
.fillMaxWidth()) {
Surface(
modifier = Modifier.size(70.dp),
shape = RectangleShape,
color = MaterialTheme.colors.onSurface.copy(alpha = 0.2f)
) {
// Image goes here
}
Column(modifier = Modifier.size(70.dp)) {
Text("Total",
fontSize = 12.sp,
color = AppGreyDark,
modifier = Modifier.padding(end = 16.dp))
Text("12,99 €",
fontSize = 18.sp,
color = AppBlackDark,
modifier = Modifier.padding(top = 4.dp))
}
}
You can apply in the Row the Arrangement.SpaceBetween.
Row(
modifier = Modifier
.padding(top = 24.dp)
.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween) {
Surface()
Column()
}
That I want to do is have a row that in the left side I can add a custom view and in the right side I need a colum with two text.
My problem comes in the left side. If I don't put a width in the left element (box) it occupies all the row and if I put a specific size of the element (box) this show the custom view looks flattened.
How can I add my customview align at the left part of the Row keeping the correct size of my custom view?
Row(
Modifier
.padding(top = 24.dp)
.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween) {
Box(modifier = Modifier
.size(width= 115.dp, height= 40.dp)
.align(Alignment.Bottom)){
Box(modifier = Modifier
.align(Alignment.BottomEnd)
.wrapContentSize()){
AndroidView(
factory = { context ->
MyView(context).apply {
seteViewListener(listener)
}
},
)
}
}
Column(modifier = Modifier.align(Alignment.Bottom)) {
Text("Total",
modifier = Modifier.fillMaxWidth(),
textAlign = TextAlign.End,
fontSize = 12.sp,
lineHeight = 16.sp,
color = colorResource(id = R.color.app_grey_dark))
Text(text = currentItem.totalPrice,
modifier = Modifier.fillMaxWidth(),
textAlign = TextAlign.End,
fontSize = 18.sp,
fontWeight = FontWeight.W500,
lineHeight = 24.sp,
color = colorResource(id = R.color.app_black_dark))
}
}