📜 ListView
1. ListView cơ bản
Phần tiêu đề “1. ListView cơ bản”Hiển thị danh sách items có thể scroll:
ListView( children: [ ListTile(title: Text('Item 1')), ListTile(title: Text('Item 2')), ListTile(title: Text('Item 3')), ],)2. ListView.builder
Phần tiêu đề “2. ListView.builder”Lazy loading - chỉ build items khi cần hiển thị:
ListView.builder( itemCount: 100, itemBuilder: (context, index) { return ListTile( title: Text('Item $index'), ); },)💡 Luôn dùng ListView.builder cho danh sách dài!
3. ListView.separated
Phần tiêu đề “3. ListView.separated”Có divider giữa các items:
ListView.separated( itemCount: 20, itemBuilder: (context, index) { return ListTile(title: Text('Item $index')); }, separatorBuilder: (context, index) { return Divider(); },)4. Scroll Direction
Phần tiêu đề “4. Scroll Direction”ListView( scrollDirection: Axis.horizontal, // Scroll ngang children: [ Container(width: 100, color: Colors.red), Container(width: 100, color: Colors.green), Container(width: 100, color: Colors.blue), ],)5. Padding
Phần tiêu đề “5. Padding”ListView.builder( padding: EdgeInsets.all(16), itemCount: 10, itemBuilder: (context, index) => ListTile(title: Text('Item $index')),)6. shrinkWrap
Phần tiêu đề “6. shrinkWrap”Cho ListView co theo nội dung (thay vì expand):
Column( children: [ Text('Header'), ListView.builder( shrinkWrap: true, // Co theo nội dung physics: NeverScrollableScrollPhysics(), // Disable scroll riêng itemCount: 5, itemBuilder: (context, index) => ListTile(title: Text('Item $index')), ), Text('Footer'), ],)⚠️ shrinkWrap tốn performance, dùng hạn chế!
7. ScrollController
Phần tiêu đề “7. ScrollController”Điều khiển scroll programmatically:
class MyList extends StatefulWidget { @override State<MyList> createState() => _MyListState();}
class _MyListState extends State<MyList> { final _controller = ScrollController();
void _scrollToTop() { _controller.animateTo( 0, duration: Duration(milliseconds: 500), curve: Curves.easeOut, ); }
@override Widget build(BuildContext context) { return Column( children: [ Expanded( child: ListView.builder( controller: _controller, itemCount: 100, itemBuilder: (context, index) => ListTile(title: Text('Item $index')), ), ), ElevatedButton(onPressed: _scrollToTop, child: Text('Scroll to top')), ], ); }}8. Pull to Refresh
Phần tiêu đề “8. Pull to Refresh”RefreshIndicator( onRefresh: () async { // Fetch new data await Future.delayed(Duration(seconds: 1)); }, child: ListView.builder( itemCount: 20, itemBuilder: (context, index) => ListTile(title: Text('Item $index')), ),)9. Infinite Scroll
Phần tiêu đề “9. Infinite Scroll”class InfiniteList extends StatefulWidget { @override State<InfiniteList> createState() => _InfiniteListState();}
class _InfiniteListState extends State<InfiniteList> { final List<int> _items = List.generate(20, (i) => i); bool _isLoading = false;
void _loadMore() async { if (_isLoading) return; setState(() => _isLoading = true);
await Future.delayed(Duration(seconds: 1));
setState(() { _items.addAll(List.generate(10, (i) => _items.length + i)); _isLoading = false; }); }
@override Widget build(BuildContext context) { return ListView.builder( itemCount: _items.length + 1, // +1 for loading indicator itemBuilder: (context, index) { if (index == _items.length) { _loadMore(); return Center(child: CircularProgressIndicator()); } return ListTile(title: Text('Item ${_items[index]}')); }, ); }}10. Ví dụ thực tế
Phần tiêu đề “10. Ví dụ thực tế”Chat List
Phần tiêu đề “Chat List”ListView.builder( reverse: true, // Scroll từ dưới lên itemCount: messages.length, itemBuilder: (context, index) { final message = messages[index]; return Align( alignment: message.isMe ? Alignment.centerRight : Alignment.centerLeft, child: Container( margin: EdgeInsets.symmetric(vertical: 4, horizontal: 8), padding: EdgeInsets.all(12), decoration: BoxDecoration( color: message.isMe ? Colors.blue : Colors.grey[300], borderRadius: BorderRadius.circular(12), ), child: Text(message.text), ), ); },)Settings Page
Phần tiêu đề “Settings Page”ListView( children: [ ListTile( leading: Icon(Icons.person), title: Text('Account'), trailing: Icon(Icons.chevron_right), onTap: () {}, ), Divider(), ListTile( leading: Icon(Icons.notifications), title: Text('Notifications'), trailing: Switch(value: true, onChanged: (v) {}), ), Divider(), ListTile( leading: Icon(Icons.dark_mode), title: Text('Dark Mode'), trailing: Switch(value: false, onChanged: (v) {}), ), ],)📝 Tóm tắt
Phần tiêu đề “📝 Tóm tắt”| Constructor | Khi nào dùng |
|---|---|
ListView() |
Ít items, static |
ListView.builder() |
Nhiều items, dynamic |
ListView.separated() |
Cần divider |
| Property | Mục đích |
|---|---|
itemCount |
Số lượng items |
scrollDirection |
Hướng scroll |
shrinkWrap |
Co theo nội dung |
physics |
Behavior scroll |
controller |
Điều khiển scroll |
reverse |
Đảo ngược thứ tự |