BasicTextField doesn't move up title on focus - android

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()
}
}

Related

How to change border color of textfield in jetpack compose?

I am trying to give a border color for textfield in jetpack compose but I couldn't find information about textfield border color or layout color I just found about How to change layout or border color of outlinedtextfield. Is there a solution like in outlinetextfield? at the textfield?
I want to do like this but for textfield
How to change the outline color of OutlinedTextField from jetpack compose?
hear is my textfield code:
TextField(
value = currentWeight,
modifier = Modifier
.fillMaxWidth()
.padding(5.dp),
onValueChange = { currentWeight = it },
label = { Text(text = "Mevcut kilon (kg)") },
shape = RoundedCornerShape(5.dp),
colors = TextFieldDefaults.textFieldColors(
textColor = Grey2,
disabledTextColor = Color.Transparent,
backgroundColor = Grey3,
focusedIndicatorColor = Color.Transparent,
unfocusedIndicatorColor = Color.Transparent,
disabledIndicatorColor = Color.Transparent,
)
)
result:
I added focused label color in textfield colors part but it didn't work
EDIT
I did it like this #Gabriele Mariotti but there are some problems
val interactionSource = remember { MutableInteractionSource() }
val isFocused = interactionSource.collectIsFocusedAsState()
val shape = RoundedCornerShape(2.dp)
val borderModifier = if (isFocused.value) Modifier.border(1.dp,Red, shape) else Modifier
val singleLine = true
val enabled = true
BasicTextField(
value = currentWeight,
onValueChange = { currentWeight = it },
interactionSource = interactionSource,
enabled = enabled,
singleLine = singleLine,
modifier = borderModifier.background(
color = TextFieldDefaults.textFieldColors().backgroundColor(true).value,
shape = shape
)
) {
TextFieldDefaults.TextFieldDecorationBox(
value = currentWeight,
innerTextField = it,
singleLine = singleLine,
enabled = enabled,
label = { Text("Label") },
placeholder = { Text("Placeholder") },
visualTransformation = VisualTransformation.None,
interactionSource = interactionSource,
colors = TextFieldDefaults.textFieldColors()
)
}
ISSUES
TextFieldDefaults.TextFieldDecorationBox
And `Text()`
TextFieldDecorationBox is red color and error is Unresolved reference: TextFieldDecorationBox
label = { Text("Label") },
placeholder = { Text("Placeholder") },
Texts error
#Composable invocations can only happen from the context of a #Composable function
You can use BasicTextField applying a border modifier and TextFieldDecorationBox.
Something like:
val isFocused = interactionSource.collectIsFocusedAsState()
val shape = RoundedCornerShape(2.dp)
val borderModifier = if (isFocused.value) Modifier.border(1.dp,Red, shape) else Modifier
BasicTextField(
value = value,
onValueChange = { value = it },
interactionSource = interactionSource,
enabled = enabled,
singleLine = singleLine,
modifier = borderModifier.background(
color = TextFieldDefaults.textFieldColors().backgroundColor(enabled).value,
shape = shape
)
) {
TextFieldDefaults.TextFieldDecorationBox(
value = value,
innerTextField = it,
singleLine = singleLine,
enabled = enabled,
label = { Text("Label") },
placeholder = { Text("Placeholder") },
visualTransformation = VisualTransformation.None,
interactionSource = interactionSource,
colors = TextFieldDefaults.textFieldColors()
)
}

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.

Removing default padding from TextField in version 1.2.0 includeFontPadding

compose_version = 1.2.0
kotlin 1.7.0
I am trying to remove the TextField. As I am using it with a trailing icon. So I can't use the BasicTextField as it doesn't have the trailing icon.
I am using version 1.2.0 and I was thinking that the includeFontPadding was false by default. However, that didn't work. So I tried to explicitly try and set it as follows:
textStyle = TextStyle(
platformStyle = PlatformTextStyle(
includeFontPadding = true
))
However, this didn't work either. So just wondering about the version 1.2.0 and removing the default padding.
Column(modifier = Modifier
.fillMaxWidth()
.background(color = Color.White)
.border(width = 2.dp, shape = RoundedCornerShape(4.dp), color = Color.LightGray)
.height(56.dp)) {
Text(
modifier = Modifier
.fillMaxWidth()
.padding(start = 16.dp),
text = "Gender (optional)")
TextField(
textStyle = TextStyle(
platformStyle = PlatformTextStyle(
includeFontPadding = true
)),
colors = TextFieldDefaults.textFieldColors(backgroundColor = Color.White),
modifier = Modifier
.fillMaxWidth(),
value = rememberMobileCode,
onValueChange = { newMobileCode ->
rememberMobileCode = newMobileCode
},
trailingIcon = {
Icon(dropdownIcon, contentDescription = "dropdown icon", modifier = Modifier.clickable {
rememberIsExpanded = !rememberIsExpanded
})
},
singleLine = true,
readOnly = true
)
}
Starting with 1.2.0 you can use the BasicTextField + TextFieldDecorationBox.
You can set the trailingIcon and you can use the contentPadding attribute to change the paddings:
val colors = TextFieldDefaults.textFieldColors()
BasicTextField(
value = text,
onValueChange = { text = it },
modifier = Modifier
.fillMaxWidth()
.background(
color = colors.backgroundColor(enabled).value,
shape = RoundedCornerShape(8.dp)
),
interactionSource = interactionSource,
enabled = enabled,
singleLine = singleLine
) {
TextFieldDefaults.TextFieldDecorationBox(
value =text,
innerTextField = it,
singleLine = singleLine,
enabled = enabled,
visualTransformation = VisualTransformation.None,
label = { Text(text = "label") },
trailingIcon = {
IconButton(onClick = { }) {
Icon(imageVector = Icons.Filled.Clear, contentDescription = "Clear")
}
},
placeholder = { /* ... */ },
interactionSource = interactionSource,
// change the padding
contentPadding = TextFieldDefaults.textFieldWithoutLabelPadding(
top = 2.dp, bottom = 2.dp
)
)
}

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