dart – Flutter TextField自动完成覆盖
发布时间:2020-12-14 14:54:35 所属栏目:百科 来源:网络整理
导读:我正在努力创建具有自动完成覆盖的TextField. 我有TextFields的表单,我想根据TextField中输入的内容显示建议. 像这样的东西: TextField autocomplete 我不确定小部件的层次结构应该是什么样的,以实现在其他小部件上方显示建议框.我应该使用Stack小部件,Over
我正在努力创建具有自动完成覆盖的TextField.
我有TextFields的表单,我想根据TextField中输入的内容显示建议. 像这样的东西: 层次结构示例的任何帮助表示赞 解决方法
我使用Stack实现了我的应用程序. TextFormField在一个容器中,ListTiles在另一个容器中,并将listtile作为用户类型覆盖在文本输入字段的容器上.你可以看看
? my app. 以下示例应用程序使用建议作为api中的用户类型,并在列表中显示哪个用户可以通过点击进行选择. > Screenshot 1 代码示例: import 'package:flutter/material.dart'; import 'package:search_suggestions/suggestions_page.dart'; void main() => runApp(new MyApp()); class MyApp extends StatelessWidget { // This widget is the root of your application. @override Widget build(BuildContext context) { return new MaterialApp( title: 'Suggestions Demo',debugShowCheckedModeBanner: false,theme: new ThemeData( brightness: Brightness.light,primarySwatch: Colors.orange,),home: new SuggestionsPage(),); } } import 'package:http/http.dart' as http; import 'dart:convert'; import 'package:flutter/material.dart'; import 'dart:io'; import 'dart:async'; class SuggestionsPage extends StatefulWidget { SuggestionsPage({Key key}) : super(key: key); @override _SuggestionsPageState createState() => new _SuggestionsPageState(); } class _SuggestionsPageState extends State<SuggestionsPage> { static const JsonCodec JSON = const JsonCodec(); final key = new GlobalKey<ScaffoldState>(); final TextEditingController _searchQueryController = new TextEditingController(); final FocusNode _focusNode = new FocusNode(); bool _isSearching = true; String _searchText = ""; List<String> _searchList = List(); bool _onTap = false; int _onTapTextLength = 0; _SuggestionsPageState() { _searchQueryController.addListener(() { if (_searchQueryController.text.isEmpty) { setState(() { _isSearching = false; _searchText = ""; _searchList = List(); }); } else { setState(() { _isSearching = true; _searchText = _searchQueryController.text; _onTap = _onTapTextLength == _searchText.length; }); } }); } @override void initState() { super.initState(); _isSearching = false; } @override Widget build(BuildContext context) { return new Scaffold( key: key,appBar: buildAppbar(context),body: buildBody(context),); } Widget getFutureWidget() { return new FutureBuilder( future: _buildSearchList(),initialData: List<ListTile>(),builder: (BuildContext context,AsyncSnapshot<List<ListTile>> childItems) { return new Container( color: Colors.white,height: getChildren(childItems).length * 48.0,width: MediaQuery.of(context).size.width,child: new ListView( // padding: new EdgeInsets.only(left: 50.0),children: childItems.data.isNotEmpty ? ListTile .divideTiles( context: context,tiles: getChildren(childItems)) .toList() : List(),); }); } List<ListTile> getChildren(AsyncSnapshot<List<ListTile>> childItems) { if (_onTap && _searchText.length != _onTapTextLength) _onTap = false; List<ListTile> childrenList = _isSearching && !_onTap ? childItems.data : List(); return childrenList; } ListTile _getListTile(String suggestedPhrase) { return new ListTile( dense: true,title: new Text( suggestedPhrase,style: Theme.of(context).textTheme.body2,onTap: () { setState(() { _onTap = true; _isSearching = false; _onTapTextLength = suggestedPhrase.length; _searchQueryController.text = suggestedPhrase; }); _searchQueryController.selection = TextSelection .fromPosition(new TextPosition(offset: suggestedPhrase.length)); },); } Future<List<ListTile>> _buildSearchList() async { if (_searchText.isEmpty) { _searchList = List(); return List(); } else { _searchList = await _getSuggestion(_searchText) ?? List(); // ..add(_searchText); List<ListTile> childItems = new List(); for (var value in _searchList) { if (!(value.contains(" ") && value.split(" ").length > 2)) { childItems.add(_getListTile(value)); } } return childItems; } } Future<List<String>> _getSuggestion(String hintText) async { String url = "SOME_TEST_API?s=$hintText&max=4"; var response = await http.get(Uri.parse(url),headers: {"Accept": "application/json"}); List decode = JSON.decode(response.body); if (response.statusCode != HttpStatus.OK || decode.length == 0) { return null; } List<String> suggestedWords = new List(); if (decode.length == 0) return null; decode.forEach((f) => suggestedWords.add(f["word"])); // String data = decode[0]["word"]; return suggestedWords; } Widget buildAppbar(BuildContext context) { return new AppBar( title: new Text('Suggestions Demo'),); } Widget buildBody(BuildContext context) { return new SafeArea( top: false,bottom: false,child: new SingleChildScrollView( padding: const EdgeInsets.symmetric(horizontal: 16.0),child: new Stack( children: <Widget>[ new Column( children: <Widget>[ Container( height: MediaQuery.of(context).size.height,child: new Column( crossAxisAlignment: CrossAxisAlignment.stretch,children: <Widget>[ const SizedBox(height: 80.0),new TextFormField( controller: _searchQueryController,focusNode: _focusNode,onFieldSubmitted: (String value) { print("$value submitted"); setState(() { _searchQueryController.text = value; _onTap = true; }); },onSaved: (String value) => print("$value saved"),decoration: const InputDecoration( border: const UnderlineInputBorder(),filled: true,icon: const Icon(Icons.search),hintText: 'Type two words with space',labelText: 'Seach words *',const SizedBox(height: 40.0),new Center( child: new RaisedButton( color: Colors.orangeAccent,onPressed: () => print("Pressed"),child: const Text( ' Search ',style: const TextStyle(fontSize: 18.0),)),const SizedBox(height: 200.0),],new Container( alignment: Alignment.topCenter,padding: new EdgeInsets.only( // top: MediaQuery.of(context).size.height * .18,top: 136.0,right: 0.0,left: 38.0),child: _isSearching && (!_onTap) ? getFutureWidget() : null) ],); } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |