我正尝试向此flutter应用程序添加搜索功能,因为从中提取数据的json文件具有7000个结果。
主要是我想搜索“ ctry”和“ peopnameincountry”。这是从https://www.youtube.com/watch?v=EwHMSxSWIvQ
中删除的..按原样..在获取json列表时效果很好,而点击以显示详细信息页面也很好。
我只需要在主页上执行搜索,因此不必滚动浏览成千上万的结果。
感谢任何帮助..谢谢大家。
if
答案 0 :(得分:1)
Try adding these function in your code:
import 'package:flutter/material.dart';
import 'dart:core';
class HomeScreen1 extends StatefulWidget {
@override
HomeScreenState createState() => HomeScreenState();
}
class HomeScreenState extends State<HomeScreen1> {
var searchController = new TextEditingController();
String search;
List<String> _filterList;
String _query = "";
bool _firstSearch = true;
@override
void initState() {
super.initState();
}
HomeScreenState() {
searchController.addListener(() {
if (searchController.text.isEmpty) {
setState(() {
_firstSearch = true;
_query = "";
});
} else {
setState(() {
_firstSearch = false;
_query = searchController.text;
});
}
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: new Container(
margin: EdgeInsets.only(left: 10.0, right: 10.0, top: 10.0),
child: new Column(
children: <Widget>[
_createSearchView(),
new Expanded(
child: _firstSearch ? _createListView() : _performSearch(),
),
],
),
),
);
}
Widget _createSearchView() {
return new Container(
decoration: BoxDecoration(border: Border.all(width: 1.0)),
child: new TextField(
controller: searchController,
decoration: InputDecoration(
icon: Icon(Icons.search),
hintText: "Search",
hintStyle: new TextStyle(color: Colors.grey[300]),
),
//textAlign: TextAlign.center,
),
);
}
Widget _createListView() {
return FutureBuilder(
future: _getUsers(),
builder: (BuildContext context, AsyncSnapshot snapshot){
print(snapshot.data);
if(snapshot.data == null){
return Container(
child: Center(
child: Text("Loading...")
)
);
} else {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
leading: Icon(Icons.arrow_forward_ios),
// leading: CircleAvatar(
// backgroundImage: NetworkImage(
// snapshot.data[index].picture
// ),
// ),
title: Text(snapshot.data[index].peopnameincountry),
subtitle: Text(snapshot.data[index].ctry),
onTap: (){
Navigator.push(context,
new MaterialPageRoute(builder: (context) => DetailPage(snapshot.data[index]))
);
},
);
},
);
}
},
),
}
Widget _performSearch() {
return FutureBuilder<List>(builder: (context, snapshot) {
_filterList = new List<String>();
for (int i = 0; i < snapshot.data.length; i++) {
var item = snapshot.data[i];
if ((item.toString().toLowerCase()).contains(_query.toLowerCase())) {
_filterList.add(item.toString());
}
}
return _createFilteredListView();
});
}
Widget _createFilteredListView() {
return ListView.builder(
itemCount: _filterList.length,
itemBuilder: (BuildContext context, int index) {
return new Card(
color: Colors.white,
elevation: 5.0,
child: new Container(
margin: EdgeInsets.all(15.0),
child: new Text("${_filterList[index]}"),
),
);
});
}
}
答案 1 :(得分:0)
FutureBuilder
小部件的概念将在收到后立即构建,但与此同时,快照完全不包含任何数据。因此,当您打电话时:
for (int i = 0; i < snapshot.data.length; i++) {
由于尚未收到数据,因此至少在开始时,您正在length
上调用null
。
解决方案是创建一个开关,并在状态完成时调用`snapshot.data:
switch (snapshot.connectionState) {
case ConnectionState.none:
return DefaultWidget(); // For instance a CircularProgress
case ConnectionState.active:
return DefaultWidget(); // For instance a CircularProgress
case ConnectionState.waiting:
return DefaultWidget(); // For instance a CircularProgress
case ConnectionState.done:
if (snapshot.hasError)
return ErrorWidget('Error: ${snapshot.error}'); //For example a Text Widget
// Your code here:
_filterList = new List<String>();
for (int i = 0; i < snapshot.data.length; i++) {
var item = snapshot.data[i];
if ((item.toString().toLowerCase()).contains(_query.toLowerCase())) {
_filterList.add(item.toString());
}
}
return _createFilteredListView();
}
return null; // unreachable
有关此here
的更多信息答案 2 :(得分:-1)
首先感谢您抽出宝贵的时间。 我遇到错误:
Another exception was thrown: NoSuchMethodError: The getter 'length' was called on null.
我认为是_performSearch窗口小部件。请查看下面的完整代码,让我知道可以解决的问题。谢谢!!!
除我尝试进行搜索时,其他所有内容都可以正常工作。
import 'package:flutter/material.dart';
import 'dart:core';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'dart:async';
class IslandWaves extends StatefulWidget {
@override
HomeScreenState createState() => HomeScreenState();
}
class HomeScreenState extends State<IslandWaves> {
var searchController = new TextEditingController();
String search;
List<String> _filterList;
String _query = "";
bool _firstSearch = true;
@override
void initState() {
super.initState();
}
HomeScreenState() {
searchController.addListener(() {
if (searchController.text.isEmpty) {
setState(() {
_firstSearch = true;
_query = "";
});
} else {
setState(() {
_firstSearch = false;
_query = searchController.text;
});
}
});
}
Future<List<User>> _getUsers() async {
var data = await http.get("https://cmfiflutterapp.s3-ap-southeast-2.amazonaws.com/UnreachedPeoplesGroup.json");
var jsonData = json.decode(data.body);
List<User> users = [];
for(var u in jsonData){
User user = User(u["ctry"], u["peopnameincountry"], u["population"], u["primarylanguagename"], u["biblestatus"], u["primaryreligion"], u["continent"]);
users.add(user);
}
print(users.length);
return users;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Unreached'),
),
body: new Container(
margin: EdgeInsets.only(left: 10.0, right: 10.0, top: 10.0),
child: new Column(
children: <Widget>[
_createSearchView(),
new Expanded(
child: _firstSearch ? _createListView() : _performSearch(),
),
],
),
),
);
}
Widget _createSearchView() {
return new Container(
decoration: BoxDecoration(border: Border.all(width: 1.0)),
child: new TextField(
controller: searchController,
decoration: InputDecoration(
icon: Icon(Icons.search),
hintText: "Search",
hintStyle: new TextStyle(color: Colors.grey[300]),
),
//textAlign: TextAlign.center,
),
);
}
Widget _createListView() {
return FutureBuilder(
future: _getUsers(),
builder: (BuildContext context, AsyncSnapshot snapshot){
print(snapshot.data);
if(snapshot.data == null){
return Container(
child: Center(
child: Text("Loading...")
)
);
} else {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
leading: Icon(Icons.arrow_forward_ios),
title: Text(snapshot.data[index].peopnameincountry),
subtitle: Text(snapshot.data[index].ctry),
onTap: (){
Navigator.push(context,
new MaterialPageRoute(builder: (context) => DetailPage(snapshot.data[index]))
);
},
);
},
);
}
},
);
}
Widget _performSearch() {
return FutureBuilder<List>(builder: (context, snapshot) {
_filterList = new List<String>();
for (int i = 0; i < snapshot.data.length; i++) {
var item = snapshot.data[i];
if ((item.toString().toLowerCase()).contains(_query.toLowerCase())) {
_filterList.add(item.toString());
}
}
return _createFilteredListView();
});
}
Widget _createFilteredListView() {
return ListView.builder(
itemCount: _filterList.length,
itemBuilder: (BuildContext context, int index) {
return new Card(
color: Colors.white,
elevation: 5.0,
child: new Container(
margin: EdgeInsets.all(15.0),
child: new Text("${_filterList[index]}"),
),
);
});
}
}
答案 3 :(得分:-1)
我道歉的家伙……我最终采用了稍微不同的方法,我认为响应速度比FutureBuilder方法稍快。也许这只是我的互联网。不确定。
import 'package:flutter/material.dart';
import 'dart:core';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'dart:async';
import 'package:progress_indicators/progress_indicators.dart';
class IslandWaves extends StatefulWidget {
@override
HomeScreenState createState() => HomeScreenState();
}
class HomeScreenState extends State<IslandWaves> {
List<User> _list = [];
List<User> _search = [];
var loading = false;
Future<Null> fetchData() async {
setState(() {
loading = true;
});
_list.clear();
final response = await http.get(
"https://cmfiflutterapp.s3-ap-southeast-2.amazonaws.com/UnreachedPeoplesGroup.json");
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
setState(() {
for (Map i in data) {
_list.add(User.formJson(i));
loading = false;
}
});
}
}
TextEditingController controller = new TextEditingController();
onSearch(String text) async {
_search.clear();
if (text.isEmpty) {
setState(() {});
return;
}
_list.forEach((f) {
if (f.ctry.contains(text) ||
f.peopnameincountry.toString().contains(text)) _search.add(f);
});
setState(() {});
}
@override
void initState() {
// TODO: implement initState
super.initState();
fetchData();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Container(
child: Column(
children: <Widget>[
Container(
padding: EdgeInsets.all(10.0),
color: Colors.blue,
child: Card(
child: ListTile(
leading: Icon(Icons.search),
title: TextField(
controller: controller,
onChanged: onSearch,
decoration: InputDecoration(
hintText: "Search", border: InputBorder.none),
),
trailing: IconButton(
onPressed: () {
controller.clear();
onSearch('');
},
icon: Icon(Icons.cancel),
),
),
),
),
loading
? Center(
heightFactor: 20.0,
child: FadingText('Loading...'),
)
: Expanded(
child: _search.length != 0 || controller.text.isNotEmpty
? ListView.builder(
itemCount: _search.length,
itemBuilder: (context, i) {
final b = _search[i];
return GestureDetector(
onTap: () {
Navigator.push(
context,
new MaterialPageRoute(
builder: (context) =>
DetailPage(_search[i])));
debugPrint('TopNav');
},
child: Container(
padding: EdgeInsets.all(10.0),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: <Widget>[
Text(
b.ctry,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 18.0),
),
SizedBox(
height: 4.0,
),
Text(b.peopnameincountry),
],
)),
);
},
)
: ListView.builder(
itemCount: _list.length,
itemBuilder: (context, i) {
final a = _list[i];
return GestureDetector(
onTap: () {
Navigator.push(
context,
new MaterialPageRoute(
builder: (context) =>
DetailPage(_list[i])));
debugPrint('BottomNav');
},
child: Container(
padding: EdgeInsets.all(10.0),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: <Widget>[
Text(
a.ctry,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 18.0),
),
SizedBox(
height: 4.0,
),
Text(a.peopnameincountry),
],
)
),
);
},
),
),
],
),
),
);
}
}
class DetailPage extends StatelessWidget{....etc.}