Flutter ListView 搜索并点击
Flutter ListView search and click
所以我目前正在尝试为我的 ListView 实现一些搜索功能,这实际上效果很好。当我输入一些字母时,它会自动显示正确的内容(-> 请参阅 Screenshot_Listview_1.png 和 Screenshot_Listview_2.png)。
只有一个问题。我希望我的列表视图中的不同文本是可点击的,所以当我点击它们时,应该会出现一个新的 ModalBottomSheet。
例如:我正在搜索“Apple”,当我单击文本“Apple”时,会打开一个 ModalBottomSheet,我可以阅读一些关于苹果的信息。
我尝试了 onTap 方法,到目前为止它仍然有效,但我只能打开相同的 BottomSheet。但是我需要不同的 BottomSheet,具体取决于我点击的内容。
这就是我到目前为止所得到的。你能帮帮我吗?我真的不知道如何解决这个问题。非常感谢!!
import 'package:flutter/material.dart';
import 'dart:ui' as ui;
class GlossarScreen extends StatefulWidget {
@override
_GlossarScreenState createState() => _GlossarScreenState();
}
class _GlossarScreenState extends State<GlossarScreen> {
TextEditingController _textEditingController = TextEditingController();
List<String> glossarListOnSearch = [];
List<String> glossarList = [
'Apple',
'Orange',
'Banana',
'Grapefruit',
'Mango',
'Kiwi',
'Grapes',
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Glossar'),
flexibleSpace: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Color(0xffFBD23E), Color(0xffF6BE03)],
begin: Alignment.topCenter,
end: Alignment.bottomCenter),
),
),
bottom: PreferredSize(
preferredSize: Size(0, 60),
child: Padding(
padding: const EdgeInsets.fromLTRB(12, 0, 12, 10),
child: Container(
//height: 50,
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.white60, Colors.white70],
begin: Alignment.topCenter,
end: Alignment.bottomCenter),
borderRadius: BorderRadius.circular(50),
),
child: Padding(
padding: const EdgeInsets.fromLTRB(20, 0, 0, 0),
child: TextField(
textAlign: TextAlign.left,
onChanged: (value) {
setState(() {
glossarListOnSearch = glossarList
.where((element) => element
.toLowerCase()
.contains(value.toLowerCase()))
.toList();
});
},
controller: _textEditingController,
decoration: InputDecoration(
border: InputBorder.none,
errorBorder: InputBorder.none,
enabledBorder: InputBorder.none,
contentPadding: EdgeInsets.all(0),
hintText: 'Search'),
),
),
),
),
),
),
body: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Color(0xffFEFDFD), Color(0xffBDBDB2)],
begin: Alignment.topLeft,
end: Alignment.bottomRight),
),
child: _textEditingController.text.isNotEmpty &&
glossarListOnSearch.isEmpty
? Column(
children: [
Align(
alignment: Alignment.center,
child: Padding(
padding: const EdgeInsets.fromLTRB(0, 50, 0, 0),
child: Text(
'No results',
style: TextStyle(
fontFamily: 'Avenir',
fontSize: 22,
color: Color(0xff848484)),
),
),
)
],
)
: ListView.builder(
itemCount: _textEditingController.text.isNotEmpty
? glossarListOnSearch.length
: glossarList.length,
itemBuilder: (context, index) {
return GestureDetector(
onTap: () {
_testFuction(context);
},
child: Padding(
padding: const EdgeInsets.fromLTRB(12, 15, 12, 15),
child: Text(
_textEditingController.text.isNotEmpty
? glossarListOnSearch[index]
: glossarList[index],
style: TextStyle(
color: Colors.black,
fontSize: 20,
fontFamily: 'Avenir'),
),
),
);
},
),
),
);
}
}
void _testFuction(context) {
showModalBottomSheet(
context: context,
builder: (BuildContext bc) {
return Scaffold(
body: Text('This text should be dependent on what I have tapped on. If I tap on "Apple" a different ModalBottomSheep shall appear then when I press on "Banana".'),
);
},
);
}
您可以使用 GestureDetector 包装 Padding 并将操作添加到 onTap 方法中。
return GestureDetector(
onTap: () {
// TODO: Add actions onTap
},
child: Padding(
padding: const EdgeInsets.fromLTRB(12, 15, 12, 15),
child: Text(
_textEditingController.text.isNotEmpty
? glossarListOnSearch[index] : glossarList[index],
style: TextStyle(
color: Colors.black, fontSize: 24, fontFamily: 'Avenir'),
),
);
);
你需要给你的 _testFuction
一些内容取决于你点击让 bottomsheet 知道它应该 show.Just 喜欢什么:
return GestureDetector(
onTap:(){
_testFuction(context,glossarListOnSearch[index]);
}
...
)
void _testFuction(context, someContent) {
showModalBottomSheet(
context: context,
builder: (BuildContext bc) {
return Scaffold(
body: Text('This is $someContent bottomsheet'),
);
},
);
}
import 'package:flutter/material.dart';
import 'dart:ui' as ui;
import 'package:stack_demo/models/FruitModel.dart';
class GlossarScreen extends StatefulWidget {
@override
_GlossarScreenState createState() => _GlossarScreenState();
}
class _GlossarScreenState extends State<GlossarScreen> {
TextEditingController _textEditingController = TextEditingController();
List<FruitModel> glossarListOnSearch = [];
List<FruitModel> glossarList = [];
@override
void initState() {
glossarList.add(FruitModel(id: 0, name: 'Apple', facts: 'Good for health'));
glossarList.add(
FruitModel(id: 1, name: 'Banana', facts: 'Banana is also for health'));
glossarList.add(
FruitModel(id: 2, name: 'Orange', facts: 'Orange good for health'));
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Glossar'),
flexibleSpace: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Color(0xffFBD23E), Color(0xffF6BE03)],
begin: Alignment.topCenter,
end: Alignment.bottomCenter),
),
),
bottom: PreferredSize(
preferredSize: Size(0, 60),
child: Padding(
padding: const EdgeInsets.fromLTRB(12, 0, 12, 10),
child: Container(
//height: 50,
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.white60, Colors.white70],
begin: Alignment.topCenter,
end: Alignment.bottomCenter),
borderRadius: BorderRadius.circular(50),
),
child: Padding(
padding: const EdgeInsets.fromLTRB(20, 0, 0, 0),
child: TextField(
textAlign: TextAlign.left,
onChanged: (value) {
setState(() {
glossarListOnSearch = glossarList
.where((element) => element.name!
.toLowerCase()
.contains(value.toLowerCase()))
.toList();
});
},
controller: _textEditingController,
decoration: InputDecoration(
border: InputBorder.none,
errorBorder: InputBorder.none,
enabledBorder: InputBorder.none,
contentPadding: EdgeInsets.all(0),
hintText: 'Search'),
),
),
),
),
),
),
body: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Color(0xffFEFDFD), Color(0xffBDBDB2)],
begin: Alignment.topLeft,
end: Alignment.bottomRight),
),
child: _textEditingController.text.isNotEmpty &&
glossarListOnSearch.isEmpty
? Column(
children: [
Align(
alignment: Alignment.center,
child: Padding(
padding: const EdgeInsets.fromLTRB(0, 50, 0, 0),
child: Text(
'No results',
style: TextStyle(
fontFamily: 'Avenir',
fontSize: 22,
color: Color(0xff848484)),
),
),
)
],
)
: ListView.builder(
itemCount: _textEditingController.text.isNotEmpty
? glossarListOnSearch.length
: glossarList.length,
itemBuilder: (context, index) {
return GestureDetector(
onTap: () {
_textEditingController.text.isNotEmpty
? _testFuction(context, glossarListOnSearch[index])
: _testFuction(context, glossarList[index]);
},
child: Padding(
padding: const EdgeInsets.fromLTRB(12, 15, 12, 15),
child: Text(
_textEditingController.text.isNotEmpty
? glossarListOnSearch[index].name!
: glossarList[index].name!,
style: TextStyle(
color: Colors.black,
fontSize: 20,
fontFamily: 'Avenir'),
),
),
);
},
),
),
);
}
}
void _testFuction(context, FruitModel model) {
showModalBottomSheet(
context: context,
builder: (BuildContext bc) {
return Scaffold(
body: Text('${model.facts}'),
);
},
);
}
所以我目前正在尝试为我的 ListView 实现一些搜索功能,这实际上效果很好。当我输入一些字母时,它会自动显示正确的内容(-> 请参阅 Screenshot_Listview_1.png 和 Screenshot_Listview_2.png)。
只有一个问题。我希望我的列表视图中的不同文本是可点击的,所以当我点击它们时,应该会出现一个新的 ModalBottomSheet。 例如:我正在搜索“Apple”,当我单击文本“Apple”时,会打开一个 ModalBottomSheet,我可以阅读一些关于苹果的信息。 我尝试了 onTap 方法,到目前为止它仍然有效,但我只能打开相同的 BottomSheet。但是我需要不同的 BottomSheet,具体取决于我点击的内容。
这就是我到目前为止所得到的。你能帮帮我吗?我真的不知道如何解决这个问题。非常感谢!!
import 'package:flutter/material.dart';
import 'dart:ui' as ui;
class GlossarScreen extends StatefulWidget {
@override
_GlossarScreenState createState() => _GlossarScreenState();
}
class _GlossarScreenState extends State<GlossarScreen> {
TextEditingController _textEditingController = TextEditingController();
List<String> glossarListOnSearch = [];
List<String> glossarList = [
'Apple',
'Orange',
'Banana',
'Grapefruit',
'Mango',
'Kiwi',
'Grapes',
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Glossar'),
flexibleSpace: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Color(0xffFBD23E), Color(0xffF6BE03)],
begin: Alignment.topCenter,
end: Alignment.bottomCenter),
),
),
bottom: PreferredSize(
preferredSize: Size(0, 60),
child: Padding(
padding: const EdgeInsets.fromLTRB(12, 0, 12, 10),
child: Container(
//height: 50,
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.white60, Colors.white70],
begin: Alignment.topCenter,
end: Alignment.bottomCenter),
borderRadius: BorderRadius.circular(50),
),
child: Padding(
padding: const EdgeInsets.fromLTRB(20, 0, 0, 0),
child: TextField(
textAlign: TextAlign.left,
onChanged: (value) {
setState(() {
glossarListOnSearch = glossarList
.where((element) => element
.toLowerCase()
.contains(value.toLowerCase()))
.toList();
});
},
controller: _textEditingController,
decoration: InputDecoration(
border: InputBorder.none,
errorBorder: InputBorder.none,
enabledBorder: InputBorder.none,
contentPadding: EdgeInsets.all(0),
hintText: 'Search'),
),
),
),
),
),
),
body: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Color(0xffFEFDFD), Color(0xffBDBDB2)],
begin: Alignment.topLeft,
end: Alignment.bottomRight),
),
child: _textEditingController.text.isNotEmpty &&
glossarListOnSearch.isEmpty
? Column(
children: [
Align(
alignment: Alignment.center,
child: Padding(
padding: const EdgeInsets.fromLTRB(0, 50, 0, 0),
child: Text(
'No results',
style: TextStyle(
fontFamily: 'Avenir',
fontSize: 22,
color: Color(0xff848484)),
),
),
)
],
)
: ListView.builder(
itemCount: _textEditingController.text.isNotEmpty
? glossarListOnSearch.length
: glossarList.length,
itemBuilder: (context, index) {
return GestureDetector(
onTap: () {
_testFuction(context);
},
child: Padding(
padding: const EdgeInsets.fromLTRB(12, 15, 12, 15),
child: Text(
_textEditingController.text.isNotEmpty
? glossarListOnSearch[index]
: glossarList[index],
style: TextStyle(
color: Colors.black,
fontSize: 20,
fontFamily: 'Avenir'),
),
),
);
},
),
),
);
}
}
void _testFuction(context) {
showModalBottomSheet(
context: context,
builder: (BuildContext bc) {
return Scaffold(
body: Text('This text should be dependent on what I have tapped on. If I tap on "Apple" a different ModalBottomSheep shall appear then when I press on "Banana".'),
);
},
);
}
您可以使用 GestureDetector 包装 Padding 并将操作添加到 onTap 方法中。
return GestureDetector(
onTap: () {
// TODO: Add actions onTap
},
child: Padding(
padding: const EdgeInsets.fromLTRB(12, 15, 12, 15),
child: Text(
_textEditingController.text.isNotEmpty
? glossarListOnSearch[index] : glossarList[index],
style: TextStyle(
color: Colors.black, fontSize: 24, fontFamily: 'Avenir'),
),
);
);
你需要给你的 _testFuction
一些内容取决于你点击让 bottomsheet 知道它应该 show.Just 喜欢什么:
return GestureDetector(
onTap:(){
_testFuction(context,glossarListOnSearch[index]);
}
...
)
void _testFuction(context, someContent) {
showModalBottomSheet(
context: context,
builder: (BuildContext bc) {
return Scaffold(
body: Text('This is $someContent bottomsheet'),
);
},
);
}
import 'package:flutter/material.dart';
import 'dart:ui' as ui;
import 'package:stack_demo/models/FruitModel.dart';
class GlossarScreen extends StatefulWidget {
@override
_GlossarScreenState createState() => _GlossarScreenState();
}
class _GlossarScreenState extends State<GlossarScreen> {
TextEditingController _textEditingController = TextEditingController();
List<FruitModel> glossarListOnSearch = [];
List<FruitModel> glossarList = [];
@override
void initState() {
glossarList.add(FruitModel(id: 0, name: 'Apple', facts: 'Good for health'));
glossarList.add(
FruitModel(id: 1, name: 'Banana', facts: 'Banana is also for health'));
glossarList.add(
FruitModel(id: 2, name: 'Orange', facts: 'Orange good for health'));
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Glossar'),
flexibleSpace: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Color(0xffFBD23E), Color(0xffF6BE03)],
begin: Alignment.topCenter,
end: Alignment.bottomCenter),
),
),
bottom: PreferredSize(
preferredSize: Size(0, 60),
child: Padding(
padding: const EdgeInsets.fromLTRB(12, 0, 12, 10),
child: Container(
//height: 50,
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.white60, Colors.white70],
begin: Alignment.topCenter,
end: Alignment.bottomCenter),
borderRadius: BorderRadius.circular(50),
),
child: Padding(
padding: const EdgeInsets.fromLTRB(20, 0, 0, 0),
child: TextField(
textAlign: TextAlign.left,
onChanged: (value) {
setState(() {
glossarListOnSearch = glossarList
.where((element) => element.name!
.toLowerCase()
.contains(value.toLowerCase()))
.toList();
});
},
controller: _textEditingController,
decoration: InputDecoration(
border: InputBorder.none,
errorBorder: InputBorder.none,
enabledBorder: InputBorder.none,
contentPadding: EdgeInsets.all(0),
hintText: 'Search'),
),
),
),
),
),
),
body: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Color(0xffFEFDFD), Color(0xffBDBDB2)],
begin: Alignment.topLeft,
end: Alignment.bottomRight),
),
child: _textEditingController.text.isNotEmpty &&
glossarListOnSearch.isEmpty
? Column(
children: [
Align(
alignment: Alignment.center,
child: Padding(
padding: const EdgeInsets.fromLTRB(0, 50, 0, 0),
child: Text(
'No results',
style: TextStyle(
fontFamily: 'Avenir',
fontSize: 22,
color: Color(0xff848484)),
),
),
)
],
)
: ListView.builder(
itemCount: _textEditingController.text.isNotEmpty
? glossarListOnSearch.length
: glossarList.length,
itemBuilder: (context, index) {
return GestureDetector(
onTap: () {
_textEditingController.text.isNotEmpty
? _testFuction(context, glossarListOnSearch[index])
: _testFuction(context, glossarList[index]);
},
child: Padding(
padding: const EdgeInsets.fromLTRB(12, 15, 12, 15),
child: Text(
_textEditingController.text.isNotEmpty
? glossarListOnSearch[index].name!
: glossarList[index].name!,
style: TextStyle(
color: Colors.black,
fontSize: 20,
fontFamily: 'Avenir'),
),
),
);
},
),
),
);
}
}
void _testFuction(context, FruitModel model) {
showModalBottomSheet(
context: context,
builder: (BuildContext bc) {
return Scaffold(
body: Text('${model.facts}'),
);
},
);
}