Флаттер TextField покрыт клавиатурой, я не могу использовать resizeToAvoidBottomInset = true - PullRequest
0 голосов
/ 20 апреля 2020

Я пытаюсь создать текстовое поле с автозаполнением, которое решает, отображать ли список предложений вверх или вниз относительно текстового поля в зависимости от того, где на экране больше места. Например:

AutocompleteTextFieldExample

Чтобы решить, в каком направлении визуализировать его, мне нужно знать, сколько места покрыто клавиатурой, поэтому я использую: "MediaQuery.of (context) .viewPadding.bottom "

Однако" MediaQuery.of (context) .viewPadding.bottom "всегда возвращает 0.0, если я установил resizeToAvoidBottomInset: true. Поэтому мне нужно установить его в ложь. Но при этом текстовые поля при фокусировке покрываются клавиатурой, как вы можете видеть на этих двух изображениях:

Экран

Экран с фокусировкой на нижнее текстовое поле

Пока это мой textFieldCode:

    class _AutoCompleteTextFieldState extends State<AutoCompleteTextField> {
  final double _maxSuggestionBoxDimension = 300;

  OverlayEntry _overlayEntry;
  final LayerLink _layerLink = LayerLink();

  final FocusNode _focusNode = FocusNode();
  final TextEditingController _textEditingController =
      new TextEditingController();

  // it contains the listTiles utilized by the overlay
  // the items are changed inside the
  List<ListTile> listTiles = [];



  @override
  void initState() {
    super.initState();

    // it inserts or remove the suggestions container depending on the focus of the textfield
    _focusNode.addListener(() {
      if (_focusNode.hasFocus) {
        this._overlayEntry = this._createOverlayEntry();
        Overlay.of(context).insert(this._overlayEntry);
      } else {
        this._overlayEntry.remove();
      }
    });

    // if text is not empty it updates the suggestion in the suggestions box
    _textEditingController.addListener(() {
      // move this logic inside updateSuggestinoContainer
      if (_textEditingController.text.isNotEmpty) {
        updateSuggestionContainer(_textEditingController.text);
      } else {
        listTiles = [];
        _overlayEntry.markNeedsBuild();
      }
    });
  }

  // it modify the suggestion container depending on the input text (in the textfield),
  // it works in 3 part
  // - defining the List of string which rappresent the suggestions that will be in the suggestions container
  // - create and assign the new List of ListTile that will be used to build the suggestions container
  // - mark _overlayEntry as dirty to rebuild and
  void updateSuggestionContainer(String text) {
    List<String> stringSuggestions = getStringSuggestions(text);
    listTiles = getListTileSuggestion(stringSuggestions);
    _overlayEntry.markNeedsBuild();
  }

  // it defines what suggestion to visualize
  List<String> getStringSuggestions(String text) {
    return widget.suggestions
        .where((possibleSuggestion) =>
            possibleSuggestion.substring(0, text.length) == text)
        .toList();
  }

  // it define how to visualize each single suggestion
  List<ListTile> getListTileSuggestion(List<String> suggestions) {
    List<ListTile> listTiles = [];
    for (String suggestion in suggestions) {
      listTiles.add(ListTile(title: Text(suggestion)));
    }
    return listTiles;
  }

  OverlayEntry _createOverlayEntry() {

    RenderBox renderBox = context.findRenderObject();
    var size = renderBox.size;
    Offset position = renderBox.localToGlobal(Offset.zero);


    Future.delayed(Duration(seconds: 3)).then((_) {
      print("${_showBottom(position.dy)}");
    });

    return OverlayEntry(
        builder: (context) => Positioned(
              width: size.width,
              child: CompositedTransformFollower(
                link: this._layerLink,
                showWhenUnlinked: false,
                offset: Offset(
                    0.0,
                    _showBottom(position.dy)
                        ? min(size.height + 5.0, _maxSuggestionBoxDimension)
                        : max(-listTiles.length * 56.0 - size.height + 40.0,
                            -_maxSuggestionBoxDimension)),
                child: Material(
                  child: Container(
                    height: min(
                        listTiles.length * 56.0, _maxSuggestionBoxDimension),
                    //duration: Duration(milliseconds: 150),
                    color: Colors.white,
                    child: MediaQuery.removePadding(
                      context: context,
                      removeTop: true,
                      child: ListView(
                          reverse: _showBottom(position.dy) ? false : true,
                          children: listTiles.isNotEmpty
                              ? ListTile.divideTiles(
                                      context: context, tiles: listTiles)
                                  .toList()
                              : List()),
                    ),
                  ),
                ),
              ),
            ));
  }

  // controll whetever the suggestion should be shown above or bottom the textField
  bool _showBottom(double textFieldCordinateY) {
    print("textFieldCordinateY = $textFieldCordinateY");
    print(
        "MediaQuery.of(context).size.height = ${MediaQuery.of(context).size.height}");
    print(
        "MediaQuery.of(context).viewInsets.bottom = ${MediaQuery.of(context).viewInsets.bottom}");
    print(
        "MediaQuery.of(context).viewPadding.bottom = ${MediaQuery.of(context).viewPadding.bottom}");

    // TODO
    // consider also the top viewInsets

    if ((MediaQuery.of(context).size.height -
                MediaQuery.of(context).viewInsets.bottom) /
            2 >
        textFieldCordinateY)
      return true;
    else
      return false;
  }

  @override
  Widget build(BuildContext context) {
    return CompositedTransformTarget(
      link: this._layerLink,
              child: TextFormField(
                //scrollPadding: EdgeInsets.all(500),
          controller: _textEditingController,
          focusNode: this._focusNode,
          decoration: InputDecoration(suffixIcon: Icon(Icons.arrow_drop_down)),
        ),
    );
  }
}

Это код сборки моего экрана:

@override
  Widget build(BuildContext context) {
    return Scaffold(
      resizeToAvoidBottomInset: false,
      appBar: AppBar(title: Text("Titolo")),
      body: ListView(children: [
        SizedBox(height: 15),
        Container(
            padding: EdgeInsets.all(20),
            child: AutoCompleteTextField(["Ape", "Areoplano", "Austronauta"])),
        SizedBox(height: 200),
        Container(
            padding: EdgeInsets.all(20),
            child: AutoCompleteTextField([
              "Biliardo",
              "Bufu",
              "Bamba",
              "Bici",
              "Bambolina",
              "Busta",
              "Bella",
              "Basta",
              "Balza"
            ])),
        SizedBox(height: 200),
        Container(
          padding: EdgeInsets.all(20),
          child: AutoCompleteTextField(["Ciru", "Capanna", "Casa"]),
        ),
      ]),
    );
  }

Заранее спасибо .

...