lzhuor / auto_size_text_field

Flutter TextField widget that automatically resizes text field to fit perfectly within its bounds.
https://pub.dev/packages/auto_size_text_field
MIT License
52 stars 35 forks source link

Contents padding consideration and multiline use #14

Closed hyobbb closed 3 years ago

hyobbb commented 3 years ago

Hi.

I found that when there's contents padding in input decoration parameter it doesn't expand enough to show every text. so I added some code at the end of "_checkTextFits" functions like below.

 double _width = tp.width;
    double _height = tp.height;
    if(widget.decoration.contentPadding!=null){
      _width = tp.width + widget.decoration.contentPadding.horizontal;
      _height = tp.height + widget.decoration.contentPadding.vertical;
    }

    //_textSpanWidth = math.max(tp.width, widget.minWidth ?? 0);
    _textSpanWidth = math.max(_width, widget.minWidth ?? 0);

    return !(tp.didExceedMaxLines ||
        _height >= constraints.maxHeight - 30 ||
        _width >= constraints.maxWidth);

For comparing height I added extra value 30 more because when there's multi line input it doesn't expand enough vertically. In general, when you put maxLines = null and keyboardType = TextInputType.multiline, it behaves badly. For example


Container(
              constraints: BoxConstraints(
                maxHeight: 380,
                maxWidth: 380,
              ),
              decoration: BoxDecoration(
                border: Border.all(width: 2, color: Colors.amber),
              ),
              child: AutoSizeTextField(
                controller: _textEditingControllerOne,
                fullwidth: false,
                autofocus: true,
                minFontSize: 0,
                maxLines: null,
                style: TextStyle(fontSize: 60),
                textAlignVertical: TextAlignVertical.center,
                decoration: InputDecoration(
                  border: InputBorder.none,
                  isDense: true,
                  contentPadding: const EdgeInsets.all(10)
                ),
                keyboardType: TextInputType.multiline,
              ),
            ),

this is what I am testing for multiline input without minimum font so that users can type text without limitation. I think for multiline text, checking algorithm to adjust fontsize should be changed. because until the textfield expand as big as it's constraints size the given fontsize should be maintained. So in that case height and width condition should be AND.

 _height >= constraints.maxHeight - 30 &&
        _width >= constraints.maxWidth

Still, It has issues for multi line use so I will dig it more. If anyone has an idea please let me know.

hyobbb commented 3 years ago

I changed the _checkTextFit result like below:

    bool exceedHeight = _height >= constraints.maxHeight;
    bool exceedWidth = _width >= constraints.maxWidth;

    if(tp.didExceedMaxLines){
      return false;
    } else if(exceedHeight) {
      return false;
    } else return true;

the original one is like this:


    return !(tp.didExceedMaxLines ||
        _height >= constraints.maxHeight ||
            _width >= constraints.maxWidth);

The thing is that actually comparing width is not necessary because if the textspan width is larger than constraint width it will either exceed max line or exceed height constraint.

Also I changed the while loop condition like below:

int i = 1;
    while (left <= right) {
      var mid = (left + (right - left) / 2).toInt();
      double scale;
      if (presetFontSizes == null) {
        scale = mid * userScale * widget.stepGranularity / style.fontSize;
      } else {
        scale = presetFontSizes[mid] * userScale / style.fontSize;
      }

      print('$i th scale : $scale');
      if (_checkTextFits(span, scale, maxLines, size)) {
        print('succeed : $left, $right');
        left = mid + 1;
        lastValueFits = true;
      } else {
        print('failed : $left, $right');
        right = mid - 1;
        left = right - 1;  //!!! added line !!!
      }
      i++;
    }

when scale doesn't fit to text I forced left to be 1 less than right so not to break the while loop until it guarantees that text would fit the size correctly. Normally it iterates 3 times more but I think it is worth.

forked version is here and any review or opinion will be welcome!

https://github.com/hyobbb/auto_size_text_field.git

lzhuor commented 3 years ago

Hi @hyobbb , thank you for the detailed analysis. Do you mind creating a PR so folks can review it and merge it once everything works out?

hyobbb commented 3 years ago

Ok. Right now I can't afford it but maybe in 2~3weeks I could pull request. Let you know then. Thanks!

hyobbb commented 3 years ago

Closing issue with PR #16