Jetpack Compose — Customize your SearchBar with BasicTextField

Rivaldy
3 min readNov 19, 2023

--

Every problem solved is a lesson learned. #AndroidTips #SolvedProblemToday

Jetpack Compose

🚀 I’m facing a TextField challenge in Jetpack Compose while crafting a cute custom SearchBar with TextField, just like this one in Figma 🎨:

SearchBar in figma

And whoopsie-daisy, the text gets snipped when set to a small form. Any solutions, you ask? Oh, just throw in some BasicTextField magic! Let’s dive into the code:

@Composable
fun SearchBar(
hint: String,
modifier: Modifier = Modifier,
isEnabled: (Boolean) = true,
height: Dp = Dimens.dp40,
elevation: Dp = Dimens.dp3,
cornerShape: Shape = RoundedCornerShape(Dimens.dp8),
backgroundColor: Color = Color.White,
onSearchClicked: () -> Unit = {},
onTextChange: (String) -> Unit = {},
) {
var text by remember { mutableStateOf(TextFieldValue()) }
Row(
modifier = Modifier
.height(height)
.fillMaxWidth()
.shadow(elevation = elevation, shape = cornerShape)
.background(color = backgroundColor, shape = cornerShape)
.clickable { onSearchClicked() },
verticalAlignment = Alignment.CenterVertically,
) {
BasicTextField(
modifier = modifier
.weight(5f)
.fillMaxWidth()
.padding(horizontal = Dimens.dp24),
value = text,
onValueChange = {
text = it
onTextChange(it.text)
},
enabled = isEnabled,
textStyle = TextStyle(
color = MaterialTheme.colorScheme.primary,
fontSize = Dimens.sp16,
fontWeight = FontWeight.Bold
),
decorationBox = { innerTextField ->
if (text.text.isEmpty()) {
Text(
text = hint,
color = Color.Gray.copy(alpha = 0.5f),
fontSize = Dimens.sp16,
fontWeight = FontWeight.Bold,
)
}
innerTextField()
},
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Text,
imeAction = ImeAction.Search
),
keyboardActions = KeyboardActions(onSearch = { onSearchClicked() }),
singleLine = true
)
Box(
modifier = modifier
.weight(1f)
.size(Dimens.dp40)
.background(color = Color.Transparent, shape = CircleShape)
.clickable {
if (text.text.isNotEmpty()) {
text = TextFieldValue(text = "")
onTextChange("")
}
},
) {
if (text.text.isNotEmpty()) {
Icon(
modifier = modifier
.fillMaxSize()
.padding(Dimens.dp10),
painter = painterResource(id = R.drawable.baseline_clear_24),
contentDescription = stringResource(R.string.search),
tint = MaterialTheme.colorScheme.primary,
)
} else {
Icon(
modifier = modifier
.fillMaxSize()
.padding(Dimens.dp10),
painter = painterResource(id = R.drawable.ic_search),
contentDescription = stringResource(R.string.search),
tint = MaterialTheme.colorScheme.primary,
)
}
}
}

Note: 🎨 Feel free to unleash your creativity by customizing the parameters of the SearchBar. You can dance with the widget icon, whether it’s doing the search tango or gracefully clearing the stage. Position it like a maestro directing a symphony! 🕺💃 Because in my case, I needed it for my dazzling Compose App.

And voila! 🎉 This is the result:

Big thanks! 🙌 This is my enchanting repository for a sample app, featuring a customized BasicTextField that’s practically doing the salsa as a SearchBar:

Feel free to tweak and remix the code. Let the coding party begin! 🚀✨

--

--

Rivaldy

Make it fun | Find me on my GitHub page at https://github.com/im-o. And let's connect over coffee! ☕ You can reach me on any social media at @rivaldy_o."