Home > Software design >  How to vertically align the text and leading/trailing icons in a TextField
How to vertically align the text and leading/trailing icons in a TextField

Time:11-27

Is there a way to set the trailing/leading icons and the text on the same level? On default it is not as shown in the image below. I tried changing the fontStyle parameter in TextField but no success. The text is shown higher than the icons

enter image description here

import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material.Icon
import androidx.compose.material.OutlinedTextField
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowForward
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.window.singleWindowApplication

fun main() = singleWindowApplication {
    var text by remember { mutableStateOf("TEXT") }
    
    OutlinedTextField(
        value = text,
        onValueChange = { text = it },
        modifier = Modifier.fillMaxWidth(),
        leadingIcon = {
            Icon(contentDescription = null,
                 imageVector = Icons.Default.ArrowForward)
        },
        trailingIcon = {
            Icon(contentDescription = null,
                 imageVector = Icons.Default.ArrowForward)
        })
}

CodePudding user response:

There are several solutions. For desktop Compose, offset the icons. For mobile Compose, adjust the baseline. And finally, just create a custom TextField.

The icons may have extra padding at the bottom. It could also be that the icons and text are always aligned to the top. You could replace the icons with ones that have no bottom padding or shift the icons up. You can tell that the icons are affecting the vertical alignment because if you comment out your icons, the text does center vertically. You could also try reducing the size of the icons.

On desktop Compose, shift the icons up:

OutlinedTextField(
     value = text,
     onValueChange = { text = it },
     modifier = Modifier.fillMaxWidth(),
     leadingIcon = {
          Icon(
                modifier = Modifier.offset(y = -3.dp),
                contentDescription = null,
                imageVector = Icons.Default.ArrowForward
          )
     },
     trailingIcon = {
          Icon(
                modifier = Modifier.offset(y = -3.dp),
                contentDescription = null,
                imageVector = Icons.Default.ArrowForward
          )
     })

On mobile devices, you can adjust the baseline of the text:

OutlinedTextField(
    value = text,
    textStyle = TextStyle(baselineShift = BaselineShift(-0.2f)),
    onValueChange = { text = it },
    modifier = Modifier.fillMaxWidth(),
    leadingIcon = {
        Icon(
            contentDescription = null,
            imageVector = Icons.Default.ArrowForward
        )
    },
    trailingIcon = {
        Icon(
            contentDescription = null,
            imageVector = Icons.Default.ArrowForward
        )
    })

Here is also a custom TextField:

class MainActivity : ComponentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContent {
            CustomTextField(
                initialText = "cool",
                onValueChange = {

                },
                onLeftButtonClick = {

                },
                onRightButtonClick = {

                }
            )
        }
    }
}

@Composable
fun CustomTextField(
    initialText: String,
    onValueChange: (text: String) -> Unit,
    onLeftButtonClick: () -> Unit,
    onRightButtonClick: () -> Unit
) {

    var text by remember { mutableStateOf(initialText) }

    Row(
        modifier = Modifier

            .fillMaxWidth()
            .wrapContentSize()
            .background(color = Color.White, shape = RoundedCornerShape(8.dp))

            .border(width = 1.dp, shape = RoundedCornerShape(8.dp), color = Color(0xFF585858))
    ) {

        ConstraintLayout(
            modifier = Modifier.fillMaxWidth()
        ) {

            val (left, mid, right) = createRefs()

            IconButton(onClick = onLeftButtonClick,
                modifier = Modifier.constrainAs(left) {
                    start.linkTo(parent.start, margin = 10.dp)
                    top.linkTo(parent.top)
                    bottom.linkTo(parent.bottom)
                }) {
                Icon(
                    contentDescription = null,
                    imageVector = Icons.Default.ArrowForward,
                )
            }


            IconButton(onClick = onRightButtonClick,
                modifier = Modifier.constrainAs(right) {
                    end.linkTo(parent.end, margin = 10.dp)
                    top.linkTo(parent.top)
                    bottom.linkTo(parent.bottom)
                }) {
                Icon(
                    contentDescription = null,
                    imageVector = Icons.Default.ArrowForward,
                )
            }

            TextField(
                value = text,
                onValueChange = {
                    text = it
                    onValueChange(it)
                },
                colors = TextFieldDefaults.textFieldColors(
                    backgroundColor = Color.White
                ),
                modifier = Modifier
                    .offset(y = 4.dp)
                    .constrainAs(mid) {
                        start.linkTo(left.end, margin = 10.dp)
                        top.linkTo(parent.top)
                        end.linkTo(right.start, margin = 10.dp)
                        bottom.linkTo(parent.bottom)
                        width = Dimension.fillToConstraints
                    })
        }
    }
  • Related