I almost completely successfully implemented the custom search component I needed, but I have one last problem. I need my component to be only 45dp to match the designer's requirements, but at that height, due to the TextField padding, it's clipping the text on top. I leave you below a screenshot of what is happening and the code I have. Is there any way to resolve this?
I'm new to Jetpack Compose and that's all I need to close this component.
#Preview
#Composable
fun SearchTextField() {
val state = remember { mutableStateOf(TextFieldValue("")) }
TextField(
value = state.value,
onValueChange = { value -> state.value = value },
textStyle = TextStyle18Normal,
placeholder = {
Text(text = stringResource(id = R.string.search), style = TextStyle18Normal)
},
trailingIcon = {
Image(
painter = painterResource(id = R.drawable.ic_search),
contentDescription = ""
)
},
singleLine = true,
shape = RoundedCornerShape(Dimen13),
colors = TextFieldDefaults.textFieldColors(
cursorColor = Color.DarkGray,
trailingIconColor = colorResource(id = R.color.purple),
backgroundColor = Color.White,
focusedIndicatorColor = Color.Transparent,
unfocusedIndicatorColor = Color.Transparent,
disabledIndicatorColor = Color.Transparent
),
modifier = Modifier
.width(Dimen320)
.height(Dimen45)
)
}
If I remove the .height(45) my problem is solved, but the component is not correct.
The TextField has hardcoded paddings.
Starting with 1.2.0 you can use the BasicTextField together with the TextFieldDecorationBox. With the contentPadding attribute you can define custom vertical paddings.
Something like:
val colors = TextFieldDefaults.textFieldColors(backgroundColor = White)
BasicTextField(
value = value,
onValueChange = onValueChange,
textStyle = TextStyle.Default.copy(fontSize = 18.sp),
modifier = modifier
.background(
color = colors.backgroundColor(enabled).value,
shape = RoundedCornerShape(13.dp). //rounded corners
)
.indicatorLine(
enabled = enabled,
isError = false,
interactionSource = interactionSource,
colors = colors,
focusedIndicatorLineThickness = 0.dp, //to hide the indicator line
unfocusedIndicatorLineThickness = 0.dp //to hide the indicator line
)
.height(45.dp),
interactionSource = interactionSource,
enabled = enabled,
singleLine = singleLine
) {
TextFieldDefaults.TextFieldDecorationBox(
value = value,
innerTextField = it,
singleLine = singleLine,
enabled = enabled,
visualTransformation = VisualTransformation.None,
trailingIcon = { /* ... */ },
placeholder = { /* ... */ },
interactionSource = interactionSource,
// keep horizontal paddings but change the vertical
contentPadding = TextFieldDefaults.textFieldWithoutLabelPadding(
top = 0.dp, bottom = 0.dp
)
)
}
Related
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()
)
}
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
What I want:
I want my OutlinedTextField to be always focused or disable the ability to focus.
I want the OutlinedTextField to be RoundedCornerShape but when I use background it goes out of the shape.
My Code:
Column(modifier = Modifier
.weight(1f)
.background(Color.Gray)
.clip(RoundedCornerShape(35.dp))
) {
OutlinedTextField(
value = "12",
onValueChange = {},
readOnly = true,
shape = RoundedCornerShape(35.dp),
textStyle = LocalTextStyle.current.copy(textAlign = TextAlign.End),
leadingIcon = { Icon(painter = painterResource(id = R.drawable.ic_coin), contentDescription = null)},
modifier = Modifier
)
}
Using enabled = false the text field will be neither editable nor focusable, the input of the text field will not be selectable, visually text field will appear in the disabled UI state readOnly.
To change the background color use the attribute backgroundColor in the TextFieldDefaults.outlinedTextFieldColors parameter:
OutlinedTextField(
value = "12",
onValueChange = {},
enabled = false,
shape = RoundedCornerShape(35.dp),
textStyle = LocalTextStyle.current.copy(textAlign = TextAlign.End),
colors = TextFieldDefaults.outlinedTextFieldColors(
backgroundColor = Color.Gray,
disabledTextColor= LocalContentColor.current.copy(LocalContentAlpha.current),
)
)
If you want to wrap the component in a Column change the order of the modifiers:
Column(modifier = Modifier
.clip(RoundedCornerShape(35.dp))
.background(Color.Gray)
){
//....
}
If you want to change the border width you have to use the version 1.2.x and the OutlinedTextFieldDecorationBox specifying the border attribute:
BasicTextField(
//....
) {
OutlinedTextFieldDecorationBox(
border = {
TextFieldDefaults.BorderBox(
//...
unfocusedBorderThickness = 4.dp,
focusedBorderThickness = 4.dp
)
}
)
}
Hi I need to remove the underline in my TextField because it look ugly when the TextField is circular. I have sat the activeColor to transparent, but then the cursor wont show (because it's transparent). How can I remove the underline/activeColor and keep the cursor?
Here is my Circular TextField code:
#Composable
fun SearchBar(value: String) {
// we are creating a variable for
// getting a value of our text field.
val inputvalue = remember { mutableStateOf(TextFieldValue()) }
TextField(
// below line is used to get
// value of text field,
value = inputvalue.value,
// below line is used to get value in text field
// on value change in text field.
onValueChange = { inputvalue.value = it },
// below line is used to add placeholder
// for our text field.
placeholder = { Text(text = "Firmanavn") },
// modifier is use to add padding
// to our text field, and a circular border
modifier = Modifier.padding(all = 16.dp).fillMaxWidth().border(1.dp, Color.LightGray, CircleShape),
shape = CircleShape,
// keyboard options is used to modify
// the keyboard for text field.
keyboardOptions = KeyboardOptions(
// below line is use for capitalization
// inside our text field.
capitalization = KeyboardCapitalization.None,
// below line is to enable auto
// correct in our keyboard.
autoCorrect = true,
// below line is used to specify our
// type of keyboard such as text, number, phone.
keyboardType = KeyboardType.Text,
),
// below line is use to specify
// styling for our text field value.
textStyle = TextStyle(color = Color.Black,
// below line is used to add font
// size for our text field
fontSize = TextUnit.Companion.Sp(value = 15),
// below line is use to change font family.
fontFamily = FontFamily.SansSerif),
// below line is use to give
// max lines for our text field.
maxLines = 1,
// active color is use to change
// color when text field is focused.
activeColor = Color.Gray,
// single line boolean is use to avoid
// textfield entering in multiple lines.
singleLine = true,
// inactive color is use to change
// color when text field is not focused.
inactiveColor = Color.Transparent,
backgroundColor = colorResource(id = R.color.white_light),
// trailing icons is use to add
// icon to the end of tet field.
trailingIcon = {
Icon(Icons.Filled.Search, tint = colorResource(id = R.color.purple_700))
},
)
You can define these attributes to apply a Transparent color:
focusedIndicatorColor
unfocusedIndicatorColor
disabledIndicatorColor
Something like:
TextField(
//..
colors = TextFieldDefaults.textFieldColors(
textColor = Color.Gray,
disabledTextColor = Color.Transparent,
backgroundColor = Color.White,
focusedIndicatorColor = Color.Transparent,
unfocusedIndicatorColor = Color.Transparent,
disabledIndicatorColor = Color.Transparent
)
)
Starting with 1.2.0 you can also use the new OutlinedTextFieldDecorationBox together with BasicTextField customizing the border or the indicator line.
val interactionSource = remember { MutableInteractionSource() }
val enabled = true
val singleLine = true
val colors = TextFieldDefaults.outlinedTextFieldColors()
BasicTextField(
value = value,
onValueChange = onValueChange,
modifier = modifier,
// internal implementation of the BasicTextField will dispatch focus events
interactionSource = interactionSource,
enabled = enabled,
singleLine = singleLine
) {
TextFieldDefaults.OutlinedTextFieldDecorationBox(
value = value,
visualTransformation = VisualTransformation.None,
innerTextField = it,
// same interaction source as the one passed to BasicTextField to read focus state
// for text field styling
interactionSource = interactionSource,
enabled = enabled,
singleLine = singleLine,
// update border thickness and shape
border = {
TextFieldDefaults.BorderBox(
enabled = enabled,
isError = false,
colors = colors,
interactionSource = interactionSource,
shape = CircleShape,
unfocusedBorderThickness = 1.dp,
focusedBorderThickness = 1.dp
)
}
)
}
Also you can use a TextFieldDecorationBox applying the indicatorLine modifier specifying the focusedIndicatorLineThickness and unfocusedIndicatorLineThickness values:
val colors = TextFieldDefaults.textFieldColors(
backgroundColor = White,
focusedIndicatorColor = Gray)
BasicTextField(
modifier = Modifier
.border(1.dp, Color.LightGray, CircleShape)
.indicatorLine(
enabled = enabled,
isError = false,
colors = colors,
interactionSource = interactionSource,
focusedIndicatorLineThickness = 0.dp,
unfocusedIndicatorLineThickness = 0.dp
)
.background(colors.backgroundColor(enabled).value, CircleShape),
) {
TextFieldDecorationBox(
//...
colors = colors
)
}
If you don't need TextField parameters / functions like collapsing label, placeholder, etc. you can use a layer of Text / BasicTextField to create a SearchField (which is a suggested workaround according to issue FilledTextField: can't remove bottom indicator ):
#Composable
fun Search(
hint: String,
endIcon: ImageVector? = Icons.Default.Cancel,
onValueChanged: (String) -> Unit,
) {
var textValue by remember { mutableStateOf(TextFieldValue()) }
Surface(
shape = RoundedCornerShape(50),
color = searchFieldColor
) {
Box(
modifier = Modifier
.preferredHeight(40.dp)
.padding(start = 16.dp, end = 12.dp),
contentAlignment = Alignment.CenterStart
)
{
if (textValue.text.isEmpty()) {
Text(
text = "Search...",
style = MaterialTheme.typography.body1.copy(color = MaterialTheme.colors.onSurface.copy(ContentAlpha.medium)),
)
}
Row(
verticalAlignment = Alignment.CenterVertically
) {
BasicTextField(
modifier = Modifier.weight(1f),
value = textValue,
onValueChange = { textValue = it; onValueChanged(textValue.text) },
singleLine = true,
cursorColor = YourColor,
)
endIcon?.let {
AnimatedVisibility(
visible = textValue.text.isNotEmpty(),
enter = fadeIn(),
exit = fadeOut()
) {
Image(
modifier = Modifier
.preferredSize(24.dp)
.clickable(
onClick = { textValue = TextFieldValue() },
indication = null
),
imageVector = endIcon,
colorFilter = iconColor
)
}
}
}
}
}
}
I would like to remove the purple line/indicator (see the following image) of TextField.
Is that possible or should I create my own custom TextField to achieve that?
This has been changed in the recent Jetpack Compose UI Beta release 1.0.0-beta01 now you can pass the
TextFieldDefaults with desired colors.
colors = TextFieldDefaults.textFieldColors(
focusedIndicatorColor = Color.Transparent,
disabledIndicatorColor = Color.Transparent,
unfocusedIndicatorColor = Color.Transparent,
backgroundColor = Color.LightGray,
)
example
TextField(
value = searchText,
onValueChange = { Log.d(HOME_COMPONENT, it) },
label = { Text(text = "Search") },
shape = RoundedCornerShape(10.dp),
leadingIcon = {
Image(
painter = painterResource(id = R.drawable.ic_search),
contentDescription = "search"
)
},
colors = TextFieldDefaults.textFieldColors(
focusedIndicatorColor = Color.Transparent,
disabledIndicatorColor = Color.Transparent,
unfocusedIndicatorColor = Color.Transparent,
backgroundColor = Color.LightGray,
)
)
image:
or if you want to customize the component according to your UI/UX then use the BasicTextField
#Composable
fun ToolbarComponent() {
var searchText by remember { mutableStateOf("") }
Row(
modifier = Modifier
.padding(16.dp)
.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically
) {
Icon(
painter = painterResource(id = R.drawable.ic_search),
contentDescription = "search",
modifier = Modifier.size(20.dp),
tint = iconTintColor
)
Spacer(modifier = Modifier.size(16.dp))
BasicTextField(
value = searchText,
onValueChange = { searchText = it },
modifier = Modifier
.background(shape = RoundedCornerShape(10.dp), color = Color.LightGray)
.fillMaxWidth()
.padding(16.dp),
decorationBox = {
Text(text = "Search")
}
)
}
}
Starting with 1.2.0-alpha04 you can use the TextFieldDecorationBox together with BasicTextField to build a custom text field based on Material Design text fields.
In your case you can apply the indicatorLine modifier to define the focusedIndicatorLineThickness and the unfocusedIndicatorLineThickness parameters:
var text by remember { mutableStateOf("") }
val singleLine = true
val enabled = true
val interactionSource = remember { MutableInteractionSource() }
BasicTextField(
value = text,
onValueChange = { text = it },
modifier = Modifier
.indicatorLine(enabled, false,
interactionSource,
TextFieldDefaults.textFieldColors(),
focusedIndicatorLineThickness = 0.dp,
unfocusedIndicatorLineThickness = 0.dp
)
.background(
TextFieldDefaults.textFieldColors().backgroundColor(enabled).value,
TextFieldDefaults.TextFieldShape
)
.width(TextFieldDefaults.MinWidth),
singleLine = singleLine,
interactionSource = interactionSource
) { innerTextField ->
TextFieldDecorationBox(
value = text,
innerTextField = innerTextField,
enabled = enabled,
singleLine = singleLine,
visualTransformation = VisualTransformation.None,
interactionSource = interactionSource,
label = { Text("Label") }
)
}
Otherwise you can use TextField defining these attributes:
focusedIndicatorColor
unfocusedIndicatorColor
disabledIndicatorColor
Something like:
TextField(
....
colors = TextFieldDefaults.textFieldColors(
backgroundColor = .....,
focusedIndicatorColor = Transparent,
unfocusedIndicatorColor = Transparent)
)
If You use TextField in that you can give the activeColor to Color.Transparent
Note: activeColor is not only for indicator, its for label bottom indicator and cursor
Ex:
var text: String by mutableStateOf("")
TextField(value = text, onValueChange = {
text = it
}, activeColor = Color.Transparent)
As per the document, activeColor is
activeColor the color of the label, bottom indicator and the cursor
when the text field is in focus
If you want to use your own you can try BaseTextField
Actually (version alpha 7) this is the easiest version I have found to remove Divider.
Set activeColor and inactiveColor to Color.Transparent in order to hide the indicator line under the TextField, whatever his state.
If you add only inactiveColor to Color.Transparent, the line will be invisible only when TextField is not focused
Add textStyle = TextStyle(color = Color.White) in order to display the color, whenever if the TextField is focused or not.
This solution will remove the line, but also the cursor indicator. It's not the best for the moment but it's also the alpha actually on Compose.
TextField(
value = MyValue,
onValueChange = { },
textStyle = TextStyle(color = Color.White),
activeColor = Color.Transparent,
inactiveColor = Color.Transparent,
shape = RoundedCornerShape(20)
)