Search code examples
htmlcssfluttercodepen

Is there a way to create this Floating Labels Form in Flutter?


Good Evening everybody, I am trying to create the shared Floating Label type UX in flutter but I am having a lot of problem, getting the things right. Here is something that I have tried and couldn't get past it;

 Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 10.0),
      child: TextField(
        style: const TextStyle(height: 1.25),
        decoration: InputDecoration(
          contentPadding: const EdgeInsets.symmetric(
            horizontal: 14.0,
            vertical: 20.0,
          ),
          focusedBorder: OutlineInputBorder(
            borderRadius: BorderRadius.circular(12),
            borderSide: const BorderSide(
              width: 3.0,
              color: Colors.black,
            ),
          ),
          label: Container(
            decoration: BoxDecoration(
              borderRadius: BorderRadius.circular(12),
              color: Colors.transparent,
            ),
            padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 14),
            child: Text(
              widget.textFieldLabel,
              style: const TextStyle(
                fontSize: 16,
                fontWeight: FontWeight.w500,
              ),
            ),
          ),
          labelStyle: const TextStyle(
            color: Colors.grey,
          ),
          floatingLabelStyle: const TextStyle(
            color: Colors.white,
          ),
          enabledBorder: OutlineInputBorder(
            borderRadius: BorderRadius.circular(12),
            borderSide: BorderSide(
              width: 2.0,
              color: Colors.grey.shade400,
            ),
          ),
        ),
      ),
    );
  }

As a beginner in flutter I have tried everything and have been stuck at this for the past 2 days. Here is the codepen url: https://codepen.io/JonLehman/pen/JjYZVwO

Any help would be greatly appreciated.


Solution

  • You are basically already there. Given that you are using a StatefulWidget since you need to update state, add a variable to keep track of your focus:

    bool isFocused = false
    

    then wrap your TextField inside a Focus widget as so:

    bool isFocused = false;
    Widget build(BuildContext context) {
      return Padding(
        padding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 10.0),
        child: Focus(
          child: TextField(
            style: const TextStyle(height: 1.25),
            decoration: InputDecoration(
              contentPadding: ...
              focusedBorder: ...
              label: Container(
                decoration: BoxDecoration(
                  borderRadius: BorderRadius.circular(12),
                  color: isFocused ? Colors.black : Colors.transparent), // Changed here
                padding: ...
                child: Text(...),
              ),
              ...
            ),
          ),
          onFocusChange: (hasFocus) {
            if (hasFocus) {
              setState(() => isFocused = true);
            } else {
              setState(() => isFocused = false);
            }
          },
        ),
      ),
    }
    

    This way, whenever it is not focused, the text will have a transparent background, but as soon as your focus on it, it'll change to a black background.

    Here is what it looks like:

    Example gif