Flutter TextField width should match width of cont

2019-07-24 21:43发布

问题:

In flutter, TextField doesn't have an intrinsic width; it only knows how to size itself to the full width of its parent container. How do I set the width to the width of the contained text.

I tried putting the TextField inside a container

As outlined here How to update flutter TextField's height and width?

new Container(              
  width: 100.0,
  child: new TextField()
)

I expect the width of the TextField to match the width of the text it contains. The TextField should grow wider as text is typed, and shrink narrower as text is deleted.

回答1:

I was able to achieve the expected result by using a TextPainter to compute the desired width of the text. I then used that width as the width of the Container containing the TextField.

Remember to call setState() in your TextFields onChanged method. This tells the widget to redraw itself causing the TextField to adjust to the new width of its content.

import 'package:flutter/material.dart';

class FitTextField extends StatefulWidget {

  final String initialValue;
  final double minWidth;

  const FitTextField({Key key, this.initialValue, this.minWidth: 30}): super(key: key);

  @override
  State<StatefulWidget> createState() => new FitTextFieldState();
}

class FitTextFieldState extends State<FitTextField>{

  TextEditingController txt = TextEditingController();

  // We will use this text style for the TextPainter used to calculate the width
  // and for the TextField so that we calculate the correct size for the text
  // we are actually displaying
  TextStyle textStyle = TextStyle(color: Colors.grey[600]);

  initState() {
    super.initState();
    // Set the text in the TextField to our initialValue
    txt.text = widget.initialValue;
  }

  @override
  Widget build(BuildContext context) {
    // Use TextPainter to calculate the width of our text
    TextSpan ts = new TextSpan(style: textStyle, text: txt.text);
    TextPainter tp = new TextPainter(text: ts, textDirection: TextDirection.ltr);
    tp.layout();
    var textWidth = tp.width; // We will use this width for the container wrapping our TextField

    // Enforce a minimum width
    if ( textWidth < widget.minWidth ) {
      textWidth = widget.minWidth;
    }

    return Container(
      width: textWidth,
      child: TextField(
        style: textStyle,
        controller: txt,
        onChanged: (text) {
          // Tells the framework to redraw the widget
          // The widget will redraw with a new width
          setState(() {});
        },
      ),
    );
  }
}