How to Change TextField Underline Color?

In Flutter, the default underline color of a TextField is determined by the current theme’s accent or primary color. However, when we want to change this behavior and set our own custom color for the underline, things get a bit tricky.

The First Attempt: Using InputDecoration

Initially, it seems like using an InputDecoration with an UnderlineInputBorder would be the way to go. We can simply set the color of the border in both the enabled and focused states:

decoration: InputDecoration(
  enabledBorder: UnderlineInputBorder(
    borderSide: BorderSide(color: Colors.cyan),
  ),
  focusedBorder: UnderlineInputBorder(
    borderSide: BorderSide(color: Colors.cyan),
  ),
)

Unfortunately, this approach doesn’t quite work as expected. The color of the underline is still determined by the current theme’s accent or primary color.

The Logical Answer: InputBorder and Theme Management

A logical assumption would be that using an InputBorder, specifically an UnderlineInputBorder, and passing it into the InputDecoration as the border, would allow us to change the underline color. However, this approach only affects whether the underline is displayed or not.

The actual color of the underline is determined by a method called _getActiveColor in the ThemeData class:

Color _getActiveColor(ThemeData themeData) {
  if (isFocused) {
    switch (themeData.brightness) {
      case Brightness.dark:
        return themeData.accentColor;
      case Brightness.light:
        return themeData.primaryColor;
    }
  }
  return themeData.hintColor;
}

This method returns the accent color for dark themes and the primary color for light themes. This is why changing the underline color using InputDecoration alone doesn’t work.

The Solution: Custom Theme Management

To change the underline color, we need to manage our theme’s colors explicitly. We can create a custom Theme with our desired colors:

new Theme(
  data: new ThemeData(
    primaryColor: Colors.red,
    accentColor: Colors.orange,
    hintColor: Colors.green
  ),
  child: new TextField(
    decoration: new InputDecoration(
      hintText: "Enter your email",
      labelText: "Email",
      labelStyle: new TextStyle(color: const Color(0xFF424242)),
      border: new UnderlineInputBorder(
        borderSide: new BorderSide(
          color: Colors.red
        )
      )
    ),
  ),
),

This approach explicitly sets the colors for the underline, and our custom theme will take precedence over the default theme.

UPDATE: The New Way to Do It

A more straightforward way to change the underline color is now available. We can simply use the InputDecoration constructor with all three border properties set:

decoration: InputDecoration(
  enabledBorder: UnderlineInputBorder(
    borderSide: BorderSide(color: theColor),
  ),
  focusedBorder: UnderlineInputBorder(
    borderSide: BorderSide(color: theColor),
  ),
  border: UnderlineInputBorder(
    borderSide: BorderSide(color: theColor),
  ),
)

This approach allows us to set our own custom color for the underline in a much simpler way.