我正在尝试创建一个自动建议输入,该输入从后端 API 获取结果。这是我的代码:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:hello_world/api.dart';
import 'package:hello_world/autocomplete_item.dart';
class Debouncer {
final int milliseconds;
VoidCallback? action;
Timer? _timer;
Debouncer({this.milliseconds = 250});
run(VoidCallback action) {
_timer?.cancel();
_timer = Timer(Duration(milliseconds: milliseconds), action);
}
}
class AutoCompleteInput extends StatefulWidget {
const AutoCompleteInput({
Key? key,
this.label = 'Suggest',
this.textInputAction,
this.validator,
this.errorMessage,
}) : super(key: key);
final String label;
final TextInputAction? textInputAction;
final FormFieldValidator<String>? validator;
final String? errorMessage;
@override
_AutoCompleteInputState createState() => _AutoCompleteInputState();
}
class _AutoCompleteInputState extends State<AutoCompleteInput> {
final _debouncer = Debouncer(milliseconds: 500);
List<AutoCompleteItem> _options = [];
bool _isLoading = false;
@override
Widget build(BuildContext context) {
return Autocomplete<AutoCompleteItem>(
displayStringForOption: (AutoCompleteItem item) => item.value,
optionsBuilder: _optionsBuilder,
fieldViewBuilder: (
BuildContext context,
TextEditingController fieldTextEditingController,
FocusNode fieldFocusNode,
VoidCallback onFieldSubmitted,
) {
return TextFormField(
controller: fieldTextEditingController,
focusNode: fieldFocusNode,
autocorrect: false,
maxLength: 50,
maxLines: 1,
keyboardType: TextInputType.text,
textInputAction: widget.textInputAction,
decoration: InputDecoration(
labelText: widget.label,
contentPadding: EdgeInsets.zero,
errorText: widget.errorMessage,
counterText: '',
suffix: _isLoading
? Padding(
padding: const EdgeInsets.only(right: 1),
child: SizedBox(
width: 20,
height: 20,
child: CircularProgressIndicator(strokeWidth: 2),
),
)
: null,
),
validator: widget.validator,
onFieldSubmitted: (String value) {
onFieldSubmitted();
},
onChanged: (text) {
_debouncer.run(() async {
setState(() => _isLoading = true);
await _fetchResults(text);
setState(() => _isLoading = false);
});
},
);
},
optionsViewBuilder: (
BuildContext context,
AutocompleteOnSelected<AutoCompleteItem> onSelected,
Iterable<AutoCompleteItem> options,
) {
return Align(
alignment: Alignment.topLeft,
child: Material(
elevation: 2,
child: Container(
width: 300,
constraints: BoxConstraints(maxHeight: 250),
child: ListView.builder(
padding: EdgeInsets.all(10.0),
itemCount: options.length,
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
final AutoCompleteItem option = options.elementAt(index);
return GestureDetector(
onTap: () {
onSelected(option);
},
child: ListTile(
dense: true,
title: Text(option.value),
),
);
},
),
),
),
);
},
onSelected: (AutoCompleteItem selection) {
print('${selection.type} => ${selection.value}');
},
);
}
Future<void> _fetchResults(String text) async {
// WE PERFORM THE HTTP REQUEST HERE AND THEN ASSIGN THE RESPONSE TO `_options`
setState(() async {
_options = await Api.fetchSuggestions(text);
});
}
Iterable<AutoCompleteItem> _optionsBuilder(
TextEditingValue textEditingValue) {
if (textEditingValue.text == '') {
return const Iterable<AutoCompleteItem>.empty();
}
return _options;
}
}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,我在的方法_fetchResults内调用方法(从 API 获取数据)。但是当获取数据并更新状态时,没有建议叠加!我检查了它的长度,它具有所有结果,但仍然没有强制小部件重建它的覆盖层。尽管当我删除 的最后一个字符时,它立即显示覆盖。我该如何解决这个问题?onChangedTextFormField_optionssetStateAutocompleteTextFormField
小智 0
在 TextField 的 onChanged 方法中调用 textEditingController.notifyListeners() 并忽略警告
例子
TextField(
onChanged: (text)async{
timer?.cancel();
timer = Timer(const Duration(milliseconds: 700), () async {
await getData(textEditingController).whenComplete((){
setState(() {
// ignore: invalid_use_of_protected_member
//invalid_use_of_visible_for_testing_member
textEditingController.notifyListeners();
});
});
});
},
)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2111 次 |
| 最近记录: |