Search code examples
androidandroid-jetpack-composeandroid-jetpack

Jetpack Compose: No background in OutlinedTextField


I have two layers in my Compose layout: One for the actual content and the one above is a Box-wrapped OutlinedTextField for search queries.

Here's the sample code:

// Placeholder for layout content
Box(modifier = Modifier.fillMaxSize()) {
    Text(
        text = stringResource(id = R.string.lorem_ipsum),
        color = Color.Gray
    )
}

// Overlaying Box with OutlinedTextField
Box(modifier = Modifier
    .padding(start = 16.dp, end = 16.dp, bottom = 16.dp, top = 64.dp)
) {
    OutlinedTextField(
        value = viewModel.query.value,
        onValueChange = { viewModel.updateQuery(it) },
        modifier = Modifier
            .fillMaxWidth()
            .align(Alignment.BottomCenter)
            .navigationBarsWithImePadding(),
        keyboardOptions = KeyboardOptions(
            capitalization = KeyboardCapitalization.Characters,
            autoCorrect = false,
            keyboardType = KeyboardType.Text,
            imeAction = ImeAction.None
        ),
        shape = CircleShape,
        colors = TextFieldDefaults.textFieldColors(
            backgroundColor = Color.White
        ),
        placeholder = { Text(stringResource(id = R.string.search_input_placeholder)) },
        maxLines = 1,
        singleLine = true
    )
}

Even though I'm setting

colors = TextFieldDefaults.textFieldColors(
        backgroundColor = Color.White
    )

in the OutlinedTextField, the background stays transparent as you can see in the following screenshot:

Enter image description here

Adding a background color on the OutlinedTextField's modifier is giving the whole row a rectangled background, which is also not the desired result.

The OutlinedTextField with it's CircleShape should only have a background inside of the shape. How can I achieve that?

I'm using Jetpack Compose version 1.0.4.


Solution

  • Reason

    Unfortunately, in version 1.0.4, OutlinedTextField ignores the backgroundColor even if you specify it, so you can remove the colors parameter.

    Support for it will be added in 1.1.0:
    https://android-review.googlesource.com/c/platform/frameworks/support/+/1741240
    It's already present in 1.1.0-alpha06 so you can play with it if you want. Your original code should produce desired outcome on that version.

    Solution

    To achieve what you want (before 1.1.0 is released) you can simply add a background modifier with the same shape:

    .background(Color.White, CircleShape)
    

    Since the order of modifiers is important, you should add it after you apply all the paddings (navigationBarsWithImePadding in your case). Like that:

    modifier = Modifier
      .fillMaxWidth()
      .align(Alignment.BottomCenter)
      .navigationBarsWithImePadding()
      .background(Color.White, CircleShape),
    

    Note: Also be aware that you cannot use the label parameter with this approach, because the TextField with label will be higher than just the outline shape and these two shaped wouldn't match in size anymore.

    Result

    Entire code:

    // Placeholder for layout content
    Box(modifier = Modifier.fillMaxSize()) {
        Text(
            text = stringResource(id = R.string.lorem_ipsum),
            color = Color.Gray
        )
    }
    
    // Overlaying Box with OutlinedTextField
    Box(modifier = Modifier
        .padding(start = 16.dp, end = 16.dp, bottom = 16.dp, top = 64.dp)
    ) {
        OutlinedTextField(
            value = viewModel.query.value,
            onValueChange = { viewModel.updateQuery(it) },
            modifier = Modifier
                .fillMaxWidth()
                .align(Alignment.BottomCenter)
                .navigationBarsWithImePadding()
                .background(Color.White, CircleShape),
            keyboardOptions = KeyboardOptions(
                capitalization = KeyboardCapitalization.Characters,
                autoCorrect = false,
                keyboardType = KeyboardType.Text,
                imeAction = ImeAction.None
            ),
            shape = CircleShape,
            placeholder = { Text(stringResource(id = R.string.search_input_placeholder)) },
            maxLines = 1,
            singleLine = true
        )
    }
    

    How the final result looks like:

    enter image description here