要實現 ListView
動態 filter,ListView
可綁定另外一個 filter 的 List
,並在 TextField
的 onChanged
event 及時改變要 filter 的 Keyword。
Version
Flutter 3.24.5
Flutter
- Android 與 iOS 都成功使用
ListView
與Event
實現動態 Filter
ListView
import 'package:flutter/material.dart';
class Home extends StatefulWidget {
const Home({super.key});
State<Home> createState() => _Home();
}
class _Home extends State<Home> {
final List<String> _allItems = [
'Apple',
'Banana',
'Cherry',
'Date',
'Elderberry',
'Fig',
'Grapes'
];
List<String> _filteredItems = [];
void initState() {
super.initState();
_filteredItems = _allItems;
}
void onChanged(String value) {
final keyword = value.trim().toLowerCase();
final filteredItems = _allItems
.where((item) => item.toLowerCase().contains(keyword))
.toList();
setState(() => _filteredItems = filteredItems);
}
Widget build(BuildContext context) {
var appBar = AppBar(
title: Text(
'Filter List',
),
);
var textField = Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(
decoration: InputDecoration(
hintText: 'Enter Keyword to Filter',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
),
),
onChanged: onChanged,
),
);
var listView = Expanded(
child: ListView.builder(
itemCount: _filteredItems.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(
_filteredItems[index],
),
);
},
),
);
var body = Column(
children: [
textField,
listView,
],
);
return Scaffold(
appBar: appBar,
body: body,
);
}
}
Line 11
final List<String> _allItems = [
'Apple',
'Banana',
'Cherry',
'Date',
'Elderberry',
'Fig',
'Grapes'
];
_allItems
:ListView
的原始資料,實務上會來自 API
Line 21
List<String> _filteredItems = [];
filteredItems
:動態 filter 過的資料,會綁定到 ListView
Line 23
void initState() {
super.initState();
_filteredItems = _allItems;
}
initState()
:一開始先將所有原始資料給 filter 過的資料
Line 60
var listView = Expanded(
child: ListView.builder(
itemCount: _filteredItems.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(
_filteredItems[index],
),
);
},
),
);
ListView
:顯示動態 filter 的資掉itemCount
:將 filter 過的資料綁定到ListView
itemBuilder()
:由 filter 過的資料建立ListTile
Line 47
var textField = Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(
decoration: InputDecoration(
hintText: 'Enter Keyword to Filter',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
),
),
onChanged: onChanged,
),
);
TextField
:輸入 keyword 供 filteronChanged()
:為了讓邊輸入邊 filter,所以寫在onChanged
event
Line 29
void onChanged(String value) {
final keyword = value.trim().toLowerCase();
final filteredItems = _allItems
.where((item) => item.toLowerCase().contains(keyword))
.toList();
setState(() => _filteredItems = filteredItems);
}
where()
:Dart 版的filter()
,當 callback 回傳為true
時為篩選條件contains()
:只要包含一部分 keyword 即可,相當於 SQL 的like
- 將 filter 結果寫入 state
Conclusion
- 要實現
ListView
動態 filter,這是最基本使用 event 的寫法,亦可使用更像Vue
computed
的getter
實現