why this two items have different width in jetpack compose - android

Hey guys I am learning textfield in jetpack compose. I want to use multiple time so I make a function and use it. when I am passing start padding it decreases the width of other one. Can someone help me on this, where i am wrong here.
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp)
) {
repeat(2){
val value = if (it == 1){
21.dp
}else {
15.dp
}
var textFieldValue by rememberSaveable(stateSaver = TextFieldValue.Saver) {
mutableStateOf(TextFieldValue())
}
TextField(
value = textFieldValue,
singleLine = true,
onValueChange = {
if (it.text.length <= 4) {
textFieldValue = it
}
},
modifier = Modifier
.height(55.dp)
.width(88.dp)
.padding(start = value),
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
colors = TextFieldDefaults.textFieldColors(
backgroundColor = OffWhite,
focusedIndicatorColor = TealLight,
cursorColor = TealLight
),
textStyle = RegularSlate20
)
}
}
It look like this
why my 2nd textfield is not 88.dp?

The order of the modifiers is important.
You have to use:
TextField(
//....
modifier = Modifier
.height(55.dp)
.padding(start = value) //apply the padding before the width modifier
.width(88.dp)
)

Related

Extra inner padding in TextField in jetpack compose

I have a TextField to enter the amount as follows:
#OptIn(ExperimentalMaterialApi::class)
#Composable
fun AmountTextField(
modifier: Modifier,
sendMoneyViewModel: SendMoneyViewModel,
isReadOnly: Boolean,
focusManager: FocusManager
) {
val paymentAmount = sendMoneyViewModel.paymentAmount.collectAsState()
val focusRequester = remember { FocusRequester() }
LaunchedEffect(Unit) {
focusRequester.requestFocus()
}
val interactionSource = remember { MutableInteractionSource() }
Row(
modifier = modifier,
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically
) {
Spacer(modifier = Modifier.weight(1f))
Text(
modifier = Modifier.wrapContentWidth(),
text = stringResource(id = R.string.rupee_symbol),
color = Black191919,
fontSize = 36.sp,
fontFamily = composeFontFamily,
fontWeight = getFontWeight(FontWeightEnum.EXTRA_BOLD)
)
BasicTextField(
modifier = Modifier
.focusRequester(focusRequester)
.background(color = YellowFFFFEAEA)
.height(IntrinsicSize.Min)
.width(IntrinsicSize.Min)
.clipToBounds(),
value = paymentAmount.value,
onValueChange = {
sendMoneyViewModel.onAmountValueChanged(it)
},
interactionSource = interactionSource,
visualTransformation = CurrencyMaskTransformation(SendMoneyViewModel.AMOUNT_MAX_LENGTH),
singleLine = true,
textStyle = TextStyle(
color = Black191919,
fontSize = 36.sp,
fontFamily = composeFontFamily,
fontWeight = getFontWeight(FontWeightEnum.EXTRA_BOLD),
textAlign = TextAlign.Center
),
keyboardActions = KeyboardActions(onDone = {
if (paymentAmount.value.isNotBlank()) {
focusManager.moveFocus(FocusDirection.Next)
}
}),
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Number, autoCorrect = false, imeAction = ImeAction.Next
),
readOnly = isReadOnly
) {
TextFieldDefaults.TextFieldDecorationBox(
value = paymentAmount.value,
visualTransformation = CurrencyMaskTransformation(SendMoneyViewModel.AMOUNT_MAX_LENGTH),
innerTextField = it,
singleLine = true,
enabled = !isReadOnly,
interactionSource = interactionSource,
contentPadding = PaddingValues(0.dp),
placeholder = { AmountFieldPlaceholder() },
colors = TextFieldDefaults.textFieldColors(
backgroundColor = Color.Transparent,
cursorColor = Color.Black,
focusedIndicatorColor = Color.Transparent,
unfocusedIndicatorColor = Color.Transparent
)
)
}
Spacer(modifier = Modifier.weight(1f))
}
}
#Composable
fun AmountFieldPlaceholder() {
Box(modifier = Modifier.fillMaxWidth(), contentAlignment = Alignment.Center) {
Text(
modifier = Modifier
.wrapContentWidth()
.align(Alignment.Center),
text = "0",
fontSize = 36.sp,
fontFamily = composeFontFamily,
fontWeight = getFontWeight(FontWeightEnum.EXTRA_BOLD),
color = GreyE3E5E5,
textAlign = TextAlign.Center
)
}
}
Initially it looks like this:
After typing "12", it's looking like this:
You can see that text "1" is cutting off.
Ideally it should look like this after typing 1234567:
But apart from actual text size, it has extra inner padding also from start and end. So it can be unexpectedly scrolled as follows:
Why TextField is having extra inner padding from start and end. Due to this, text is cutting while typing.
I have tried many solutions like:
Resizeable BasicTextField in Jetpack Compose
I also tried to set WindowInsets, but nothing is working.
I will suggest using View's EditText here since it provides lots of flexibility in terms of customization.
I have pasted the code on Paste Bin https://pastebin.com/Z1hS7xns
Update: wrap buildAmountEditText() with remember{} otherwise it'll be created every time there's new message string
#Composable
fun AmountTextField(
amount: String,
onAmountChange: (String) -> Unit
) {
Row(
horizontalArrangement = Arrangement.SpaceAround,
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = stringResource(R.string.rupee_symbol),
style = MaterialTheme.typography.h2.copy(
color = Color(0xFF191919),
fontWeight = FontWeight.ExtraBold
)
)
val titleField = remember {
buildAmountEditText(
context = LocalContext.current,
amount = amount,
onAmountChange = onAmountChange,
placeholder = "0",
focusChangeListener = { _, hasFocus ->
// do something with focus
},
paddingValues = PaddingValues(0)
)
}
AndroidView(factory = { titleField })
}
}
Remove singleLine property or set it as false. This is the simplest solution.

How to resize after adding a new element using Jetpack compose?

I wrote the composable below (shown as dialog). When viewState.errorCode != 0, another composable is shown. This all works fine, but the height of the box doesn't adjust when the new composable becomes visible.This results in an 'invisible overflow' whereby a number of items are no longer visible. Is there a way to make the box dynamic so that it adjusts in height when a new element becomes visible?
Box(modifier = Modifier
.clip(RoundedCornerShape(4.dp))) {
Column(
modifier = Modifier
.background(MaterialTheme.colors.onPrimary, MaterialTheme.shapes.large)
.padding(12.dp)
) {
Text(stringResource(R.string.verify_hint, user.email).parseBold(), fontSize = 18.textDp, fontFamily = SourceSans)
if (viewState.errorCode != 0) {
AlertMessage(message = stringResource(id = viewState.errorCode), color = errorColor, padding = PaddingValues(top = 12.dp))
}
TextField(
value = code,
onValueChange = { code = it },
label = { Text(stringResource(R.string.verification_code)) },
colors = TextFieldDefaults.textFieldColors(backgroundColor = textFieldColor),
singleLine = true,
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
modifier = Modifier
.fillMaxWidth()
.padding(top = 12.dp, bottom = 12.dp)
)
NMButton(
onClick = { viewModel.verify(user, code, verifyLogin, language = context.getLanguageBasedOnConfiguration()) },
modifier = Modifier
.fillMaxWidth()
.padding(start = 0.dp, end = 0.dp),
icon = R.drawable.ic_badge_check_solid,
label = stringResource(R.string.verify)
)
}
if (viewState.loading) {
Loader()
}
}
Yes there is.
You can use animateContentSize on your box modifier
then you declare an animationSpec like below:
Box(modifier = Modifier
.animateContentSize(
animationSpec = tween(
durationMillis = 300,
easing = LinearOutSlowInEasing
)
).clip(RoundedCornerShape(4.dp))
)
Now if the AlertMessage appears it will animate the size of the box.
You can also create expandable cards with this approach.
This video may help you too.

BasicTextField doesn't move up title on focus

Hi this is my BasicTextField :
fun TextFieldRow(data: TextFieldData) {
val interactionSource = remember { MutableInteractionSource() }
val text by data.text.observeAsState("")
Row(
modifier = Modifier
.fillMaxWidth()
.padding(start = 20.dp, end = 20.dp, top = 17.dp)
) {
BasicTextField(
value = text,
onValueChange = {
data.text.value = it
},
modifier = Modifier
.padding(vertical = 6.dp)
.fillMaxWidth()
.indicatorLine(
enabled = true,
isError = false,
interactionSource = interactionSource,
colors = TextFieldDefaults.textFieldColors()
)
) { innerTextField ->
TextFieldDefaults.TextFieldDecorationBox(
value = text,
innerTextField = innerTextField,
enabled = true,
singleLine = true,
visualTransformation = VisualTransformation.None,
interactionSource = interactionSource,
contentPadding = TextFieldDefaults.textFieldWithLabelPadding(start = 4.dp),
label = { Text(text = data.label) }
)
}
}
}
I set the label in the TextFieldDecorationBox. It work well when I type some letters (the title goes up), but when I just take focus, the title stay in the middle. Any help ?
EDIT
I would like something like that, the reason why I use BasicTextField instead of TextField is because I want to manage padding.
You can change innerTextField like;
BasicTextField(
//
){ innerTextField ->
Box{
if(text.value.isEmpty())
Text(
text = "Title",
color = Color.Black.copy(alpha = 0.5f)
)
innerTextField()
}
}

How do I change the internal margins in the OutlinedTextField? [duplicate]

I want to customize TextField composable in Jetpack Compose. I am trying to achieve the result in the image below, but somehow TextField has some default paddings which i couldn't find how to change values of. I want to remove default paddings and customize it
(The image on the right one is the result i achieved. I drew a border so that you can see it has padding, btw below that TextField are just Text composables, they aren't TextFields)
Below is my TextField code
TextField(
value = "",
onValueChange = {},
modifier = Modifier
.weight(1F)
.padding(0.dp)
.border(width = 1.dp, color = Color.Red),
placeholder = {
Text(
"5555 5555 5555 5555", style = TextStyle(
color = Color.Gray
)
)
},
colors = TextFieldDefaults.textFieldColors(
backgroundColor = Color.Transparent,
unfocusedIndicatorColor = Color.Transparent,
focusedIndicatorColor = Color.Transparent
),
)
You can use BasicTextField, it's a plain text field without any decorations. Note that it doesn't have placeholder/hint too, you have to implement those by yourself if you need.
BasicTextField(value = "", onValueChange = {}, Modifier.fillMaxWidth())
Since 1.2.0-alpha04 it's much easier to make your BasicTextField look like TextField or OutlinedTextField. You can copy source code of TextField, which is pretty short since most of logic was moved into TextFieldDefaults.TextFieldDecorationBox, and pass the needed padding value into contentPadding parameter of TextFieldDefaults.TextFieldDecorationBox.
In the latest alpha release (androidx.compose.material:material:1.2.0-alpha04) they exposed TextFieldDefaults.TextFieldDecorationBox.
This is the implementation of the decorationBox composable used in the material TextField implementation.
You can use it as follows:
val interactionSource = remember { MutableInteractionSource() }
BasicTextField(
value = value,
onValueChange = onValueChange,
modifier = modifier,
visualTransformation = visualTransformation,
interactionSource = interactionSource,
enabled = enabled,
singleLine = singleLine,
) { innerTextField ->
TextFieldDefaults.TextFieldDecorationBox(
value = value,
visualTransformation = visualTransformation,
innerTextField = innerTextField,
singleLine = singleLine,
enabled = enabled,
interactionSource = interactionSource,
contentPadding = PaddingValues(0.dp), // this is how you can remove the padding
)
}
This will allow you to remove the padding but still get the rest of the features that come with TextField.
Remember to use the same MutableInteractionSource for both the BasicTextField and the TextFieldDefaults.TextFieldDecorationBox.
The official documentation I linked to above shows more examples if its usage.
Thank you all, i did use BasicTextField and achieved the result i wanted :)
#Composable
fun BottomOutlineTextField(placeholder: String, value: String, onValueChange: (String) -> Unit) {
BasicTextField(
modifier = Modifier.fillMaxWidth(),
value = value,
onValueChange = onValueChange,
textStyle = TextStyle(
color = if (isSystemInDarkTheme()) Color(0xFF969EBD) else Color.Gray
),
decorationBox = { innerTextField ->
Row(modifier = Modifier.fillMaxWidth()) {
if (value.isEmpty()) {
Text(
text = placeholder,
color = if (isSystemInDarkTheme()) Color(0xFF969EBD) else Color.Gray,
fontSize = 14.sp
)
}
}
innerTextField()
}
)
}
I wanted to cut off the 16.dp at the start. I managed to this in the following way:
BoxWithConstraints(modifier = Modifier
.clipToBounds()
) {
TextField(modifier = Modifier
.requiredWidth(maxWidth+16.dp)
.offset(x=(-8).dp))
}
I solved this problem by coping all source code from TextField and replace this lines of code :
val paddingToIcon = TextFieldPadding - HorizontalIconPadding
// val padding = Modifier.padding(
// start = if (leading != null) paddingToIcon else TextFieldPadding,
// end = if (trailing != null) paddingToIcon else TextFieldPadding
// )
val padding = Modifier.padding(
start = if (leading != null) paddingToIcon else 0.dp,
end = if (trailing != null) paddingToIcon else 0.dp
)
And this work great!
You can put your TextField in a Box and apply modifiers, e.g.
Box(
modifier = Modifier.background(
shape = RoundedCornerShape(percent = 10),
color = colorBackgroundGray
)
) {
TextField(
value = text,
onValueChange = onValueChange,
modifier = Modifier.fillMaxWidth().padding(8.dp, 0.dp, 0.dp, 0.dp)...
}
Using
...
decorationBox{
TextFieldDefaults.TextFieldDecorationBox(
....
)
required me to add the anotation #OptIn(ExperimentalMaterialApi::class) which seems to not be a good aproach for a release scenario.
Instead, I could get the result I as expecteing by the following implementation:
#Composable
fun Input(
text: TextFieldValue = TextFieldValue(),
onValueChanged: (TextFieldValue) -> Unit = { },
keyboardType: KeyboardType = KeyboardType.Text,
imeAction: ImeAction = ImeAction.Done,
isEnable: Boolean = true,
singleLine: Boolean = true,
shape: Shape = rounded,
autoCorrect: Boolean = false,
innerPadding: PaddingValues = PaddingValues(15.dp, 7.dp)
) {
val focusManager = LocalFocusManager.current
val fontSize = 16.sp
BasicTextField(
value = text,
onValueChange = onValueChanged,
Modifier
.clip(shape)
.border(1.dp, Color.Gray, shape)
.background(Color.White),
textStyle = TextStyle(color = Color.Black, fontSize = fontSize),
enabled = isEnable,
singleLine = singleLine,
keyboardOptions = KeyboardOptions(
KeyboardCapitalization.None,
autoCorrect,
keyboardType,
imeAction
),
keyboardActions = KeyboardActions(
onAny = {
focusManager.clearFocus()
}
),
decorationBox = {
Box(
modifier = Modifier.padding(innerPadding)
) {
if(text.text.isBlank()) {
Text(
text = "Search",
style = TextStyle(color = Color.Black, fontSize = fontSize)
)
}
it()
}
}
)
}
Hope it helps somebody.
It is so easy, just copy all TextField or OutlinedTextField functions and remove defaultMinSize then add contentPadding
After that, you can use it instead of main TextField or OutlinedTextField
for OutlinedTextField:
#Composable
fun BorderTextField(
value: String,
onValueChange: (String) -> Unit,
modifier: Modifier = Modifier,
enabled: Boolean = true,
readOnly: Boolean = false,
textStyle: TextStyle = LocalTextStyle.current,
label: #Composable (() -> Unit)? = null,
placeholder: #Composable (() -> Unit)? = null,
leadingIcon: #Composable (() -> Unit)? = null,
trailingIcon: #Composable (() -> Unit)? = null,
isError: Boolean = false,
visualTransformation: VisualTransformation = VisualTransformation.None,
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
keyboardActions: KeyboardActions = KeyboardActions.Default,
singleLine: Boolean = false,
maxLines: Int = Int.MAX_VALUE,
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
shape: Shape = MaterialTheme.shapes.small,
colors: TextFieldColors = TextFieldDefaults.outlinedTextFieldColors()
) {
// If color is not provided via the text style, use content color as a default
val textColor = textStyle.color.takeOrElse {
colors.textColor(enabled).value
}
val mergedTextStyle = textStyle.merge(TextStyle(color = textColor))
#OptIn(ExperimentalMaterialApi::class)
BasicTextField(
value = value,
modifier = if (label != null) {
modifier
// Merge semantics at the beginning of the modifier chain to ensure padding is
// considered part of the text field.
.semantics(mergeDescendants = true) {}
} else {
modifier
}
.background(colors.backgroundColor(enabled).value, shape),
onValueChange = onValueChange,
enabled = enabled,
readOnly = readOnly,
textStyle = mergedTextStyle,
cursorBrush = SolidColor(colors.cursorColor(isError).value),
visualTransformation = visualTransformation,
keyboardOptions = keyboardOptions,
keyboardActions = keyboardActions,
interactionSource = interactionSource,
singleLine = singleLine,
maxLines = maxLines,
decorationBox = #Composable { innerTextField ->
TextFieldDefaults.OutlinedTextFieldDecorationBox(
value = value,
visualTransformation = visualTransformation,
innerTextField = innerTextField,
placeholder = placeholder,
label = label,
leadingIcon = leadingIcon,
trailingIcon = trailingIcon,
singleLine = singleLine,
enabled = enabled,
isError = isError,
interactionSource = interactionSource,
colors = colors,
contentPadding = TextFieldDefaults.outlinedTextFieldPadding(
start = 0.dp,
top = 0.dp,
end = 0.dp,
bottom = 0.dp
),
border = {
TextFieldDefaults.BorderBox(
enabled,
isError,
interactionSource,
colors,
shape
)
}
)
}
)
}
Actually that is innate, it follows material guidelines. If you wish to disable it, an alternative could be to set the height of the TextField explicitly, and matching it with the font size of the text. That way it will only extend till the text does. Another way would be to look at the source of TextField. You could just copy the source and make modifications to meet your requirements. The former sounds like an easy fix, however, the latter is no big deal as well. It is doable, and is a recommended practice to customize behavior for your needs. Also, just as a side note, I don't think it is a good idea to disable that padding. It was added to design guidelines since it seems pretty sensible and natural to have it. Sometimes we find some designs attractive when we think about them but they aren't as good when seen implemented.

remove default padding on jetpack compose textfield

I want to customize TextField composable in Jetpack Compose. I am trying to achieve the result in the image below, but somehow TextField has some default paddings which i couldn't find how to change values of. I want to remove default paddings and customize it
(The image on the right one is the result i achieved. I drew a border so that you can see it has padding, btw below that TextField are just Text composables, they aren't TextFields)
Below is my TextField code
TextField(
value = "",
onValueChange = {},
modifier = Modifier
.weight(1F)
.padding(0.dp)
.border(width = 1.dp, color = Color.Red),
placeholder = {
Text(
"5555 5555 5555 5555", style = TextStyle(
color = Color.Gray
)
)
},
colors = TextFieldDefaults.textFieldColors(
backgroundColor = Color.Transparent,
unfocusedIndicatorColor = Color.Transparent,
focusedIndicatorColor = Color.Transparent
),
)
You can use BasicTextField, it's a plain text field without any decorations. Note that it doesn't have placeholder/hint too, you have to implement those by yourself if you need.
BasicTextField(value = "", onValueChange = {}, Modifier.fillMaxWidth())
Since 1.2.0-alpha04 it's much easier to make your BasicTextField look like TextField or OutlinedTextField. You can copy source code of TextField, which is pretty short since most of logic was moved into TextFieldDefaults.TextFieldDecorationBox, and pass the needed padding value into contentPadding parameter of TextFieldDefaults.TextFieldDecorationBox.
In the latest alpha release (androidx.compose.material:material:1.2.0-alpha04) they exposed TextFieldDefaults.TextFieldDecorationBox.
This is the implementation of the decorationBox composable used in the material TextField implementation.
You can use it as follows:
val interactionSource = remember { MutableInteractionSource() }
BasicTextField(
value = value,
onValueChange = onValueChange,
modifier = modifier,
visualTransformation = visualTransformation,
interactionSource = interactionSource,
enabled = enabled,
singleLine = singleLine,
) { innerTextField ->
TextFieldDefaults.TextFieldDecorationBox(
value = value,
visualTransformation = visualTransformation,
innerTextField = innerTextField,
singleLine = singleLine,
enabled = enabled,
interactionSource = interactionSource,
contentPadding = PaddingValues(0.dp), // this is how you can remove the padding
)
}
This will allow you to remove the padding but still get the rest of the features that come with TextField.
Remember to use the same MutableInteractionSource for both the BasicTextField and the TextFieldDefaults.TextFieldDecorationBox.
The official documentation I linked to above shows more examples if its usage.
Thank you all, i did use BasicTextField and achieved the result i wanted :)
#Composable
fun BottomOutlineTextField(placeholder: String, value: String, onValueChange: (String) -> Unit) {
BasicTextField(
modifier = Modifier.fillMaxWidth(),
value = value,
onValueChange = onValueChange,
textStyle = TextStyle(
color = if (isSystemInDarkTheme()) Color(0xFF969EBD) else Color.Gray
),
decorationBox = { innerTextField ->
Row(modifier = Modifier.fillMaxWidth()) {
if (value.isEmpty()) {
Text(
text = placeholder,
color = if (isSystemInDarkTheme()) Color(0xFF969EBD) else Color.Gray,
fontSize = 14.sp
)
}
}
innerTextField()
}
)
}
I wanted to cut off the 16.dp at the start. I managed to this in the following way:
BoxWithConstraints(modifier = Modifier
.clipToBounds()
) {
TextField(modifier = Modifier
.requiredWidth(maxWidth+16.dp)
.offset(x=(-8).dp))
}
I solved this problem by coping all source code from TextField and replace this lines of code :
val paddingToIcon = TextFieldPadding - HorizontalIconPadding
// val padding = Modifier.padding(
// start = if (leading != null) paddingToIcon else TextFieldPadding,
// end = if (trailing != null) paddingToIcon else TextFieldPadding
// )
val padding = Modifier.padding(
start = if (leading != null) paddingToIcon else 0.dp,
end = if (trailing != null) paddingToIcon else 0.dp
)
And this work great!
You can put your TextField in a Box and apply modifiers, e.g.
Box(
modifier = Modifier.background(
shape = RoundedCornerShape(percent = 10),
color = colorBackgroundGray
)
) {
TextField(
value = text,
onValueChange = onValueChange,
modifier = Modifier.fillMaxWidth().padding(8.dp, 0.dp, 0.dp, 0.dp)...
}
Using
...
decorationBox{
TextFieldDefaults.TextFieldDecorationBox(
....
)
required me to add the anotation #OptIn(ExperimentalMaterialApi::class) which seems to not be a good aproach for a release scenario.
Instead, I could get the result I as expecteing by the following implementation:
#Composable
fun Input(
text: TextFieldValue = TextFieldValue(),
onValueChanged: (TextFieldValue) -> Unit = { },
keyboardType: KeyboardType = KeyboardType.Text,
imeAction: ImeAction = ImeAction.Done,
isEnable: Boolean = true,
singleLine: Boolean = true,
shape: Shape = rounded,
autoCorrect: Boolean = false,
innerPadding: PaddingValues = PaddingValues(15.dp, 7.dp)
) {
val focusManager = LocalFocusManager.current
val fontSize = 16.sp
BasicTextField(
value = text,
onValueChange = onValueChanged,
Modifier
.clip(shape)
.border(1.dp, Color.Gray, shape)
.background(Color.White),
textStyle = TextStyle(color = Color.Black, fontSize = fontSize),
enabled = isEnable,
singleLine = singleLine,
keyboardOptions = KeyboardOptions(
KeyboardCapitalization.None,
autoCorrect,
keyboardType,
imeAction
),
keyboardActions = KeyboardActions(
onAny = {
focusManager.clearFocus()
}
),
decorationBox = {
Box(
modifier = Modifier.padding(innerPadding)
) {
if(text.text.isBlank()) {
Text(
text = "Search",
style = TextStyle(color = Color.Black, fontSize = fontSize)
)
}
it()
}
}
)
}
Hope it helps somebody.
It is so easy, just copy all TextField or OutlinedTextField functions and remove defaultMinSize then add contentPadding
After that, you can use it instead of main TextField or OutlinedTextField
for OutlinedTextField:
#Composable
fun BorderTextField(
value: String,
onValueChange: (String) -> Unit,
modifier: Modifier = Modifier,
enabled: Boolean = true,
readOnly: Boolean = false,
textStyle: TextStyle = LocalTextStyle.current,
label: #Composable (() -> Unit)? = null,
placeholder: #Composable (() -> Unit)? = null,
leadingIcon: #Composable (() -> Unit)? = null,
trailingIcon: #Composable (() -> Unit)? = null,
isError: Boolean = false,
visualTransformation: VisualTransformation = VisualTransformation.None,
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
keyboardActions: KeyboardActions = KeyboardActions.Default,
singleLine: Boolean = false,
maxLines: Int = Int.MAX_VALUE,
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
shape: Shape = MaterialTheme.shapes.small,
colors: TextFieldColors = TextFieldDefaults.outlinedTextFieldColors()
) {
// If color is not provided via the text style, use content color as a default
val textColor = textStyle.color.takeOrElse {
colors.textColor(enabled).value
}
val mergedTextStyle = textStyle.merge(TextStyle(color = textColor))
#OptIn(ExperimentalMaterialApi::class)
BasicTextField(
value = value,
modifier = if (label != null) {
modifier
// Merge semantics at the beginning of the modifier chain to ensure padding is
// considered part of the text field.
.semantics(mergeDescendants = true) {}
} else {
modifier
}
.background(colors.backgroundColor(enabled).value, shape),
onValueChange = onValueChange,
enabled = enabled,
readOnly = readOnly,
textStyle = mergedTextStyle,
cursorBrush = SolidColor(colors.cursorColor(isError).value),
visualTransformation = visualTransformation,
keyboardOptions = keyboardOptions,
keyboardActions = keyboardActions,
interactionSource = interactionSource,
singleLine = singleLine,
maxLines = maxLines,
decorationBox = #Composable { innerTextField ->
TextFieldDefaults.OutlinedTextFieldDecorationBox(
value = value,
visualTransformation = visualTransformation,
innerTextField = innerTextField,
placeholder = placeholder,
label = label,
leadingIcon = leadingIcon,
trailingIcon = trailingIcon,
singleLine = singleLine,
enabled = enabled,
isError = isError,
interactionSource = interactionSource,
colors = colors,
contentPadding = TextFieldDefaults.outlinedTextFieldPadding(
start = 0.dp,
top = 0.dp,
end = 0.dp,
bottom = 0.dp
),
border = {
TextFieldDefaults.BorderBox(
enabled,
isError,
interactionSource,
colors,
shape
)
}
)
}
)
}
Actually that is innate, it follows material guidelines. If you wish to disable it, an alternative could be to set the height of the TextField explicitly, and matching it with the font size of the text. That way it will only extend till the text does. Another way would be to look at the source of TextField. You could just copy the source and make modifications to meet your requirements. The former sounds like an easy fix, however, the latter is no big deal as well. It is doable, and is a recommended practice to customize behavior for your needs. Also, just as a side note, I don't think it is a good idea to disable that padding. It was added to design guidelines since it seems pretty sensible and natural to have it. Sometimes we find some designs attractive when we think about them but they aren't as good when seen implemented.

Categories

Resources