import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.BasicText
import androidx.compose.foundation.text.input.TextFieldLineLimits
import androidx.compose.foundation.text.input.rememberTextFieldState
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.composeunstyled.TextInput
import com.composeunstyled.UnstyledTextField
@Composable
fun TextFieldDemo() {
val displayName = rememberTextFieldState()
val fieldShape = RoundedCornerShape(8.dp)
Box(
modifier = Modifier
.fillMaxSize()
.padding(horizontal = 16.dp)
.padding(top = 16.dp)
.imePadding(),
contentAlignment = Alignment.Center,
) {
Box(
modifier = Modifier
.widthIn(max = 500.dp),
contentAlignment = Alignment.Center,
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
) {
UnstyledTextField(
state = displayName,
modifier = Modifier.fillMaxWidth(),
lineLimits = TextFieldLineLimits.SingleLine,
cursorBrush = SolidColor(Color.Black),
textStyle = TextStyle(
color = Color.Black,
fontSize = 14.sp,
lineHeight = 20.sp,
),
) {
Column {
BasicText(
"Display Name",
modifier = Modifier.padding(bottom = 8.dp),
style = TextStyle(
color = Color.Black,
fontSize = 16.sp,
lineHeight = 24.sp,
),
)
TextInput(
Modifier
.fillMaxWidth()
.background(Color(0xFFF8FAFC), fieldShape)
.border(1.dp, Color(0xFFCACACA), fieldShape)
.padding(horizontal = 16.dp, vertical = 12.dp),
placeholder = {
BasicText(
"Alex",
style = TextStyle(
color = Color.Black.copy(0.6f),
fontSize = 14.sp,
lineHeight = 20.sp,
),
)
},
)
}
}
}
}
}
}Features
- State-based text input
- Placeholder slot
- Input and output transformations
- Text style parameters
Installation
implementation("com.composables:composeunstyled-text-field")
Anatomy
UnstyledTextField(state = state) {
TextInput()
}
Concepts
UnstyledTextFieldrepresents the text field container.TextInputrenders the editable text and optional placeholder.
Accessibility
Use accessibilityLabel when the text field does not include a readable label in its content.
Code Examples
Adding placeholder text
Use the placeholder parameter on TextInput to render content while the field is empty:
val state = rememberTextFieldState()
UnstyledTextField(state = state) {
TextInput(
placeholder = {
BasicText("Email")
},
)
}
Creating a single-line text field
Use the lineLimits parameter to restrict input to one line:
UnstyledTextField(
state = state,
lineLimits = TextFieldLineLimits.SingleLine,
) {
TextInput()
}
Setting the keyboard type
Use the keyboardOptions parameter to request a specific software keyboard:
UnstyledTextField(
state = state,
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Email),
) {
TextInput()
}
Styling entered text
Use the text style parameters to set the style of the editable text:
UnstyledTextField(
state = state,
fontWeight = FontWeight.Medium,
textColor = Color.Black,
) {
TextInput()
}
Labeling an icon-only text field
Use the accessibilityLabel parameter when the visible text field has no text label:
UnstyledTextField(
state = state,
accessibilityLabel = "Search",
) {
TextInput()
}
API Reference
UnstyledTextField
| Parameter | Type | Description |
|---|---|---|
state |
TextFieldState |
The TextFieldState that manages the text field's content. |
modifier |
Modifier |
Modifier to be applied to the text input. |
enabled |
Boolean |
|
accessibilityLabel |
String? |
|
readOnly |
Boolean |
|
cursorBrush |
Brush |
The brush to use for the cursor. |
textStyle |
TextStyle |
Style to apply to the text. |
textAlign |
TextAlign |
Alignment of the text. |
lineHeight |
TextUnit |
Height of each line of text. |
fontSize |
TextUnit |
Size of the font. |
letterSpacing |
TextUnit |
Spacing between letters. |
fontWeight |
FontWeight? |
Weight of the font. |
fontFamily |
FontFamily? |
Family of the font. |
textDecoration |
TextDecoration? |
|
lineLimits |
TextFieldLineLimits |
|
inputTransformation |
InputTransformation? |
|
outputTransformation |
OutputTransformation? |
|
onTextLayout |
(Density.(getResult: () -> TextLayoutResult?) -> Unit)? |
|
onKeyboardAction |
KeyboardActionHandler? |
Handler for keyboard actions. |
keyboardOptions |
KeyboardOptions |
Options for the keyboard. |
interactionSource |
MutableInteractionSource? |
Interaction source for the text field. |
textColor |
Color |
Color of the text. |
scrollState |
ScrollState |
Scroll state for the text field. |
content |
TextFieldScope.() -> Unit |
Content composable that defines the text field's appearance. |
TextFieldScope.TextInput
| Parameter | Type | Description |
|---|---|---|
modifier |
Modifier |
Modifier to be applied to the text input. |
placeholder |
(() -> Unit)? |
Placeholder composable when the field is empty. |