最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

dart - How do I wrap a label in a TextFormField while keeping the floating label behavior in Flutter? - Stack Overflow

programmeradmin2浏览0评论

I am trying to create a TextFormField with a label that can wrap to multiple lines if the text is long. However, I want to keep the floating label behavior, which is the default behavior where the label moves above the field when the user focuses on it.

  1. The label to wrap when the text is long.
  2. The floating label behavior, where the label floats above the input field when the user starts typing.
TextFormField(
            decoration: InputDecoration(
              labelText: label,
              labelStyle: TextStyle(
                color: Colors.grey.shade700,
                fontSize: 16,
              ),

              floatingLabelBehavior: FloatingLabelBehavior.auto,
              contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 16),
              

I attempted using a Column to separate the label and the TextFormField, but that also didn’t give me the floating label effect.

child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          // Label text
          Padding(
            padding: const EdgeInsets.symmetric(horizontal: 12),
            child: Text(
              label,
              style: TextStyle(
                color: Colors.grey.shade700,
                fontSize: 16,
              ),
              maxLines: null, // Allow label text to wrap if needed
              overflow: TextOverflow.visible,
            ),
          ),
          // Input field
          TextFormField(
            controller: controller,
            keyboardType: TextInputType.number,
            style: const TextStyle(
              color: Colors.black,
              fontSize: 15,
            ),
            minLines: 1,
            maxLines: null,
            floatingLabelBehavior: FloatingLabelBehavior.auto,
            contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 16),
              

This only make the label wrap but it does not make it float to the top, and the text input wraps using minLine and maxLine which I don't need.

Basically, I can make the label float and not wrap and I can make it wrap but not float.

I want it to wrap and float.

I am trying to create a TextFormField with a label that can wrap to multiple lines if the text is long. However, I want to keep the floating label behavior, which is the default behavior where the label moves above the field when the user focuses on it.

  1. The label to wrap when the text is long.
  2. The floating label behavior, where the label floats above the input field when the user starts typing.
TextFormField(
            decoration: InputDecoration(
              labelText: label,
              labelStyle: TextStyle(
                color: Colors.grey.shade700,
                fontSize: 16,
              ),

              floatingLabelBehavior: FloatingLabelBehavior.auto,
              contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 16),
              

I attempted using a Column to separate the label and the TextFormField, but that also didn’t give me the floating label effect.

child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          // Label text
          Padding(
            padding: const EdgeInsets.symmetric(horizontal: 12),
            child: Text(
              label,
              style: TextStyle(
                color: Colors.grey.shade700,
                fontSize: 16,
              ),
              maxLines: null, // Allow label text to wrap if needed
              overflow: TextOverflow.visible,
            ),
          ),
          // Input field
          TextFormField(
            controller: controller,
            keyboardType: TextInputType.number,
            style: const TextStyle(
              color: Colors.black,
              fontSize: 15,
            ),
            minLines: 1,
            maxLines: null,
            floatingLabelBehavior: FloatingLabelBehavior.auto,
            contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 16),
              

This only make the label wrap but it does not make it float to the top, and the text input wraps using minLine and maxLine which I don't need.

Basically, I can make the label float and not wrap and I can make it wrap but not float.

I want it to wrap and float.

Share Improve this question asked Mar 11 at 11:42 disaldisal 111 silver badge2 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 1

To create a TextFormField with a label that can wrap to multiple lines if the text is long You can build a custom border

=> Demo Video of the provided solution: CustomLable_with_UnderlineInputBorder

Step 1: Define the FocusNode and isFocused

Declare a FocusNode and a isFocused to track the focus state, then initialize it in the initState

  late final FocusNode _focusNode;

  bool isFocused = false;

  @override
  void initState() {
    _focusNode = FocusNode();

    _focusNode.addListener(
      () {
        setState(
          () {
            isFocused = _focusNode.hasFocus;
            log("Is Field Focued : $isFocused");
          },
        );
      },
    );
    super.initState();
  }

Step 2: Define the Label you want

String label = "This very very very very very long lable to test the custom label widget";

Step 3: Create the TextFormField with a Custom Border

    Scaffold(
      resizeToAvoidBottomInset: false,
      appBar: AppBar(
        title: const Text("Custom Lable"),
        centerTitle: true,
        automaticallyImplyLeading: false,
        backgroundColor: Colors.green,
      ),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: <Widget>[
          Container(
            margin: const EdgeInsets.symmetric(horizontal: 10.0),
            decoration: BoxDecoration(
              border: Border(
                bottom: isFocused
                    ? const BorderSide(color: Colors.blue, width: 2.0)
                    : const BorderSide(color: Colors.black),
              ),
            ),
            child: TextFormField(
              focusNode: _focusNode,
              onTapOutside: (event) {
                FocusScope.of(context).unfocus();
              },
              decoration: InputDecoration(
                border: InputBorder.none,
                label: Text(label),
                focusedBorder: const OutlineInputBorder(
                  borderSide: BorderSide(
                    color: Colors.transparent,
                    width: 0.0,
                  ),
                ),
              ),
            ),
          )
        ],
      ),
    );

As You can see :

  • You can use the

    border: Border(
      bottom: isFocused
              ? const BorderSide(color: Colors.blue, width: 2.0)
              : const BorderSide(color: Colors.black),
    ),
    
  • As the UnderlineInputBorder and control its decoration using isFocus bool

  • To implement this mechanism the border must be OutlineInputBorder

  • To remove the TextField border and use the Container border use

    border: InputBorder.none,
    
  • Make sure to give the OutlineInputBorder :

  • borderSide: BorderSide(
      color: Colors.transparent,
      width: 0.0,
    ),
    

To display a label above a TextFormField when it is focused, you can use the Focus widget along with a bool isFocused to manage the focus state

=> Demo Video of the Provided Solution: CustomLable

Step 3: Build the TextField Widget

    Scaffold(
      resizeToAvoidBottomInset: false,
      appBar: AppBar(
        title: const Text("Custom Lable"),
        centerTitle: true,
        automaticallyImplyLeading: false,
        backgroundColor: Colors.green,
      ),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: <Widget>[
          if (isFocused) ...{
            Row(
              children: <Widget>[
                Expanded(
                  child: Padding(
                    padding: const EdgeInsets.all(8.0),
                    child: Text(
                      label,
                      style: TextStyle(
                        color: Colors.grey.shade700,
                        fontSize: 16,
                      ),
                    ),
                  ),
                ),
              ],
            ),
          },
          Padding(
            padding: const EdgeInsets.symmetric(horizontal: 10),
            child: TextFormField(
              focusNode: _focusNode,
              onTapOutside: (event) {
                // Use this to unFocus the Field when user Tap any where
                FocusScope.of(context).unfocus();
              },
              decoration: InputDecoration(
                enabledBorder: OutlineInputBorder(
                  borderRadius: BorderRadius.circular(20),
                  borderSide: const BorderSide(color: Colors.grey),
                ),
                focusedBorder: OutlineInputBorder(
                  borderRadius: BorderRadius.circular(20),
                  borderSide: const BorderSide(color: Colors.green),
                ),
                fillColor: Colors.grey.shade100,
                filled: true,
                label: isFocused
                    ? null
                    : Text(
                        label,
                        style: TextStyle(
                          color: Colors.grey.shade700,
                          fontSize: 16,
                        ),
                      ),
              ),
            ),
          ),
        ],
      ),
    );

As you can see:

  • The label is null when the isFocued is true

  • And the label will positioned above the TextField when the isFocus true

Use label instead of labelText. Because label accepts the widget.

This is the output for the below code

TextFormField(
    decoration: InputDecoration(
        label: Text(
            "This is a long label that should wrap and float above the input field",
            softWrap: true, // Allow the text to wrap
            style: TextStyle(color: Colors.grey.shade700, fontSize: 16),
        ),
        floatingLabelBehavior:
            FloatingLabelBehavior.auto, // Enable floating label
            contentPadding: const EdgeInsets.symmetric(
                horizontal: 12,
                vertical: 16,
            ),
            border: OutlineInputBorder(borderRadius: BorderRadius.circular(8)),
        ),
    ),
);

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论