Flutter 键盘覆盖的颤振文本字段,我可以';t使用resizeToAvoidBottomInset=true
我正在尝试创建一个自动完成的文本字段,根据屏幕上的空间大小决定是否向上或向下显示文本字段的建议列表。像这样: 为了决定可视化的方向,我需要知道键盘覆盖了多少空间,所以我使用:“MediaQuery.of(context.viewPadding.bottom” 但是,如果我设置resizeToAvoidBottomInset:true,则“MediaQuery.of(context).viewPadding.bottom”始终返回0.0。 所以我需要把它设为假。但这样做时,当聚焦时,文本字段被键盘覆盖,正如您在这两幅图中所看到的: 这是到目前为止我的文本字段代码:Flutter 键盘覆盖的颤振文本字段,我可以';t使用resizeToAvoidBottomInset=true,flutter,flutter-layout,textfield,scaffold,Flutter,Flutter Layout,Textfield,Scaffold,我正在尝试创建一个自动完成的文本字段,根据屏幕上的空间大小决定是否向上或向下显示文本字段的建议列表。像这样: 为了决定可视化的方向,我需要知道键盘覆盖了多少空间,所以我使用:“MediaQuery.of(context.viewPadding.bottom” 但是,如果我设置resizeToAvoidBottomInset:true,则“MediaQuery.of(context).viewPadding.bottom”始终返回0.0。 所以我需要把它设为假。但这样做时,当聚焦时,文本字段被键
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)),
),
);
}
}
提前感谢。添加您尝试的代码。尝试将您的构建包装在
SingleChildScrollView中
屏幕中的文本字段位于列表视图中,我尝试用SingleChildScrollView将构建包装在_AutocompleteTextFieldState中,但它没有做任何事情。我还尝试用SingleChildScrollView替换列表视图,将其替换为列内部。但是不管你尝试了什么,它都不起作用。试着将你的构建包装在一个SingleChildScrollView
屏幕中的文本字段在一个列表视图中,我尝试用SingleChildScrollView将构建包装在_AutocompleteTextFieldState中,但它没有做任何事情。我还尝试用SingleChildScrollView替换列表视图,将其替换为列内部。但它也不起作用
@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"]),
),
]),
);
}