英文:
how to make name search feature in flutter
问题
这是你提供的代码部分:
List<Data> data = [];
List<Data> allData = [];
List<Data> _foundData = [];
@override
initState() {
_foundData = allData;
super.initState();
}
@override
void dispose() {
_foundData.clear();
super.dispose();
}
void _runFilter(String enteredKeyword) {
List<Data> results = [];
if (enteredKeyword.isEmpty) {
results = allData;
} else {
results = allData
.where(
(user) => user.name!.toLowerCase().contains(
enteredKeyword.toLowerCase(),
),
)
.toList();
}
setState(() {
_foundData = results;
});
}
@override
Widget build(BuildContext context) {
// ... (其余部分被省略)
}
如果你有任何关于这段代码的问题或需要进一步的帮助,请随时告诉我。
英文:
I'm having a problem doing a name search, where when I type the name of a user, it doesn't appear the way I want and doesn't filter according to the name I'm looking for.
List<Data> data = [];
List<Data> allData = [];
List<Data> _foundData = [];
@override
initState() {
_foundData = allData;
super.initState();
}
@override
void dispose() {
_foundData.clear();
super.dispose();
}
void _runFilter(String enteredKeyword) {
List<Data> results = [];
if (enteredKeyword.isEmpty) {
results = allData;
} else {
results = allData
.where(
(user) => user.name!.toLowerCase().contains(
enteredKeyword.toLowerCase(),
),
)
.toList();
}
setState(() {
_foundData = results;
});
}`
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: backgroundColor,
appBar: const PreferredSize(
preferredSize: Size.fromHeight(kToolbarHeight),
child: CustomAppbar(
title: 'Dosen',
),
),
body: Center(
child: Padding(
padding: const EdgeInsets.only(
left: 16,
top: 16,
right: 16,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.only(bottom: 8),
child: TextField(
onChanged: (value) => _runFilter(value),
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
width: 1,
color: Colors.grey.shade300,
),
borderRadius: BorderRadius.circular(10),
),
focusedBorder: OutlineInputBorder(
borderSide: const BorderSide(
width: 1,
color: Color.fromARGB(255, 255, 255, 255),
),
borderRadius: BorderRadius.circular(10),
),
hintText: 'Cari nama dosen...',
fillColor: const Color.fromARGB(255, 255, 255, 255),
filled: true,
hintStyle: TextStyle(
color: greyColor,
),
suffixIcon: Icon(
Icons.search,
color: greyColor,
),
),
),
),
FutureBuilder<List<Data>>(
future: ListDosenProvider.getDosen(),
builder: (context, snapshot) {
if (snapshot.hasData) {
if (snapshot.connectionState == ConnectionState.done) {
return Expanded(
child: ListView.builder(
physics: const BouncingScrollPhysics(),
itemCount: snapshot.data!.length,
// itemCount: allData.length,
// itemCount: _foundData.length,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.only(top: 14),
child: Container(
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: const BorderRadius.all(
Radius.circular(8),
),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.2),
spreadRadius: 1,
blurRadius: 9,
offset: const Offset(
1,
2,
),
),
],
),
child: Padding(
padding: const EdgeInsets.all(14),
child: Row(
children: [
Image.asset(
'assets/images/user.png',
width: 50,
),
const SizedBox(
width: 10,
),
Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
snapshot.data![index].name
.toString(),
style: bold6,
),
Text(
snapshot.data![index].prodi
.toString(),
style: regular6,
),
const SizedBox(
width: 8,
),
const SizedBox(
height: 5,
),
SizedBox(
height: 30,
width: 90,
child: ElevatedButton.icon(
onPressed: () {
Navigator.of(context).pop();
// ignore: deprecated_member_use
launch(
'mailto:${snapshot.data![index].email.toString()}',
);
},
icon: Icon(
Icons.mail,
size: 17,
color: primaryColor,
),
label: Text('Email',
style: bold6.copyWith(
color: primaryColor,
)),
style: ElevatedButton.styleFrom(
backgroundColor: const Color(
0xffC5D5FF,
),
),
),
),
],
),
],
),
),
),
);
},
),
);
}
} else if (snapshot.hasError) {
return Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
// crossAxisAlignment: CrossAxisAlignment.center,
children: [
Center(
child: Image.asset(
'assets/images/server.png',
height: 100,
),
),
const SizedBox(
height: 20,
),
Text(
'Upsss... Server error!',
style: regular4,
)
],
),
);
}
return Expanded(
child: Center(
child: CircularProgressIndicator(color: primaryColor),
),
);
},
),
],
),
),
),
);
}
I've been looking for a way and doing it according to the instructions above but it still doesn't work when I do a name search
enter image description here
答案1
得分: 1
你必须使用 _foundData
来列出数据。在某些情况下,如果用户在加载之前输入搜索,可能会无法正常工作。因此,我使用 TextEditingController
在每次构建时过滤搜索结果,以便我们可以保留用户输入。
将你的代码替换为以下内容:
List<Data> allData = [];
List<Data> _foundData = [];
final searchController = TextEditingController();
@override
void dispose() {
_foundData.clear();
super.dispose();
}
void _runFilter(String enteredKeyword) {
List<Data> results = [];
if (enteredKeyword.trim().isEmpty) {
results = allData;
} else {
results = allData
.where(
(user) => user.name!.toLowerCase().contains(
enteredKeyword.trim().toLowerCase(),
),
)
.toList();
}
_foundData = results;
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: backgroundColor,
appBar: const PreferredSize(
preferredSize: Size.fromHeight(kToolbarHeight),
child: CustomAppbar(
title: 'Dosen',
),
),
body: Center(
child: Padding(
padding: const EdgeInsets.only(
left: 16,
top: 16,
right: 16,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.only(bottom: 8),
child: TextField(
onChanged: (value) => setState(() {}),
controller: searchController,
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
width: 1,
color: Colors.grey.shade300,
),
borderRadius: BorderRadius.circular(10),
),
focusedBorder: OutlineInputBorder(
borderSide: const BorderSide(
width: 1,
color: Color.fromARGB(255, 255, 255, 255),
),
borderRadius: BorderRadius circular(10),
),
hintText: 'Cari nama dosen...',
fillColor: Color.fromARGB(255, 255, 255, 255),
filled: true,
hintStyle: TextStyle(
color: greyColor,
),
suffixIcon: Icon(
Icons.search,
color: greyColor,
),
),
),
),
FutureBuilder<List<Data>>(
future: ListDosenProvider.getDosen(),
builder: (context, snapshot) {
if (snapshot.hasData) {
if (snapshot.connectionState == ConnectionState.done) {
allData = snapshot.data!;
_runFilter(searchController.text);
return Expanded(
child: ListView.builder(
physics: BouncingScrollPhysics(),
itemCount: _foundData.length,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.only(top: 14),
child: Container(
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(
Radius.circular(8),
),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.2),
spreadRadius: 1,
blurRadius: 9,
offset: Offset(
1,
2,
),
),
],
),
child: Padding(
padding: const EdgeInsets.all(14),
child: Row(
children: [
Image.asset(
'assets/images/user.png',
width: 50,
),
SizedBox(
width: 10,
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
_foundData[index].name.toString(),
style: bold6,
),
Text(
_foundData[index].prodi.toString(),
style: regular6,
),
SizedBox(
width: 8,
),
SizedBox(
height: 5,
),
SizedBox(
height: 30,
width: 90,
child: ElevatedButton.icon(
onPressed: () {
Navigator.of(context).pop();
launch(
'mailto:${_foundData[index].email.toString()}',
);
},
icon: Icon(
Icons.mail,
size: 17,
color: primaryColor,
),
label: Text('Email',
style: bold6.copyWith(
color: primaryColor,
)),
style: ElevatedButton.styleFrom(
backgroundColor: Color(0xffC5D5FF),
),
),
),
],
),
],
),
),
),
);
},
),
);
}
} else if (snapshot.hasError) {
return Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Center(
child: Image.asset(
'assets/images/server.png',
height: 100,
),
),
SizedBox(
height: 20,
),
Text(
'Upsss... Server error!',
style: regular4,
)
],
),
);
}
return Expanded(
child: Center(
child: CircularProgressIndicator(color: primaryColor),
),
);
},
),
],
),
),
),
);
}
希望这有所帮助。
英文:
You have to use _foundData
to list data. In some case, if use enters search before load that may not work. So I filter the search result on every build by using TextEditingController
, so that we can persist user input.
Replace you code with following..
List<Data> allData = [];
List<Data> _foundData = [];
final searchController = TextEditingController();
@override
void dispose() {
_foundData.clear();
super.dispose();
}
void _runFilter(String enteredKeyword) {
List<Data> results = [];
if (enteredKeyword.trim().isEmpty) {
results = allData;
} else {
results = allData
.where(
(user) => user.name!.toLowerCase().contains(
enteredKeyword.trim().toLowerCase(),
),
)
.toList();
}
_foundData = results;
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: backgroundColor,
appBar: const PreferredSize(
preferredSize: Size.fromHeight(kToolbarHeight),
child: CustomAppbar(
title: 'Dosen',
),
),
body: Center(
child: Padding(
padding: const EdgeInsets.only(
left: 16,
top: 16,
right: 16,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.only(bottom: 8),
child: TextField(
onChanged: (value) => setState(() {}),
controller: searchController,
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
width: 1,
color: Colors.grey.shade300,
),
borderRadius: BorderRadius.circular(10),
),
focusedBorder: OutlineInputBorder(
borderSide: const BorderSide(
width: 1,
color: Color.fromARGB(255, 255, 255, 255),
),
borderRadius: BorderRadius.circular(10),
),
hintText: 'Cari nama dosen...',
fillColor: const Color.fromARGB(255, 255, 255, 255),
filled: true,
hintStyle: TextStyle(
color: greyColor,
),
suffixIcon: Icon(
Icons.search,
color: greyColor,
),
),
),
),
FutureBuilder<List<Data>>(
future: ListDosenProvider.getDosen(),
builder: (context, snapshot) {
if (snapshot.hasData) {
if (snapshot.connectionState == ConnectionState.done) {
allData = snapshot.data!;
_runFilter(searchController.text);
return Expanded(
child: ListView.builder(
physics: const BouncingScrollPhysics(),
itemCount: _foundData.length,
// itemCount: allData.length,
// itemCount: _foundData.length,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.only(top: 14),
child: Container(
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: const BorderRadius.all(
Radius.circular(8),
),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.2),
spreadRadius: 1,
blurRadius: 9,
offset: const Offset(
1,
2,
),
),
],
),
child: Padding(
padding: const EdgeInsets.all(14),
child: Row(
children: [
Image.asset(
'assets/images/user.png',
width: 50,
),
const SizedBox(
width: 10,
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
_foundData[index].name.toString(),
style: bold6,
),
Text(
_foundData[index].prodi.toString(),
style: regular6,
),
const SizedBox(
width: 8,
),
const SizedBox(
height: 5,
),
SizedBox(
height: 30,
width: 90,
child: ElevatedButton.icon(
onPressed: () {
Navigator.of(context).pop();
// ignore: deprecated_member_use
launch(
'mailto:${_foundData[index].email.toString()}',
);
},
icon: Icon(
Icons.mail,
size: 17,
color: primaryColor,
),
label: Text('Email',
style: bold6.copyWith(
color: primaryColor,
)),
style: ElevatedButton.styleFrom(
backgroundColor: const Color(
0xffC5D5FF,
),
),
),
),
],
),
],
),
),
),
);
},
),
);
}
} else if (snapshot.hasError) {
return Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
// crossAxisAlignment: CrossAxisAlignment.center,
children: [
Center(
child: Image.asset(
'assets/images/server.png',
height: 100,
),
),
const SizedBox(
height: 20,
),
Text(
'Upsss... Server error!',
style: regular4,
)
],
),
);
}
return Expanded(
child: Center(
child: CircularProgressIndicator(color: primaryColor),
),
);
},
),
],
),
),
),
);
}
I hope this helps.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论