Các loại ListView
Chúng ta bắt đầu tìm hiểu các loại listview và sau đó sẽ tìm cách chỉnh sửa các tính năng của chúng. Đây là các loại listview chúng ta cần tìm hiểu :
- ListView
- ListView.builder
- ListView.separated
- ListView.custom
Bây giờ chúng ta sẽ đi tìm hiểu từng cái :
1. ListView
Một ListView chứa các item con và có thể cuộn được :
Code:
ListView( children: <Widget>[ ItemOne(), ItemTwo(), ItemThree(), ],
),
Thông thường đối với loại trên sẽ sử dụng với số lượng children (số item) nhỏ nếu bạn cố xây dựng với lượng lớn thì sẽ gây tốn bộ nhớ khiến view bị giật lag.
2. ListView.builder
Contructor builder sẽ repeat số item . Hàm contructor này có 2 params:
itemCount: Tổng số item trong list. itemBuilder: sẽ tạo view cho từng item.
Code:
ListView.builder( itemCount: itemCount, itemBuilder: (context, position) { return listItem(); },
),
Các item được xây dựng theo cơ chế resuable nghĩa là các item đã được cuộn và ko hiển thị ở màn hình sẽ được tái sử dụng cho các item được hiển thị .
Neat trick: Vì các phẩn tử được tải một cách lười biếng và chỉ cần số phần tử hiển thị trên màn hình nên không cần thiết tổng số item như là 1 pramas bắt buộc và có thể load item đến vô hạn .
3. ListView.separated
Khi sử dụng ListView này thì giữa các item sẽ có khoảng cách
Trong hàm constructor này có 2 thành phần : main list item và list khoảng cách item. Tuy nhiên hàm này ko giống ListView.builder phải cần số itemCount .
ListView.separated( itemBuilder: (context, position) { return ListItem(); }, separatorBuilder: (context, position) { return SeparatorItem(); }, itemCount: itemCount,
),
4. ListView.custom
Hàm custom() cho phép tạo các ListViews với các thành phần con tuỳ chỉnh. Các số tham số tuỳ chỉnh bắt buộc :
1. SliverChildListDelegate
2. SliverChildBuilderDelegate
SliverChildListDelegate cho phép trực tiếp các list child item nhưng SliverChildBuiderDelegate cho phép IndexedWidgetBuilder(function builder chúng tôi dùng).
Contructor ListView giống với ListView.custom khi dùng SliverChildListDelegate
Tôi đã giới thiệu các bạn loại ListView , bây giờ hãy xem qua ScrollPhysics.
ScrollPhysics
Để kiểm soát cách cuộn của các ListView chúng ta sẽ đặt thêm 1 param vào trong các hàm constructor của ListView. Các loại cuộn :
- NeverScrollableScrollPhysics
- BouncingScrollPhysics
- ClampingScrollPhysics
- FixedExtentScrollPhysics
1. NeverScrollableScrollPhysics
Đúng như tên gọi dùng để disable việc scroll của listview.
2. BouncingScrollPhysics
Khi cuộn đến item cuối cùng thì nó sẽ trả về item đầu tiên .
Bạn có thể xem ảnh demo ở đây :
3. ClampingScrollPhysics
Đây là cách cuộn hay được dùng ở bên Android. Khi cuộn đến item cuối cùng thì sẽ có 1 hiệu ứng.
4. FixedExtentScrollPhysics
Cách cuộn này hơi khác với các cách cuộn trên và chỉ làm việc với FixedExtendScrollControllers . Nó chỉ cuộn đến item có offset ở giữa.
Code :
FixedExtentScrollController fixedExtentScrollController = new FixedExtentScrollController();
ListWheelScrollView( controller: fixedExtentScrollController, physics: FixedExtentScrollPhysics(), children: monthsOfTheYear.map((month) { return Card( child: Row( children: <Widget>[ Expanded( child: Padding( padding: const EdgeInsets.all(8.0), child: Text( month, style: TextStyle(fontSize: 18.0), ), )), ], )); }).toList(), itemExtent: 60.0,
),
Một số điều cần biết
1, Làm cách nào để các phần tử không bị destroy và vẫn tồn tại trong list ?
TL : Flutter cung cấp hàm KeepAlive() để giúp các item không bị destroy. Trong list , các phần tử sẽ được wrap default bằng widget AutomaticKeepAlive
AutomaticKeepAlives có thể disable bằng set addAutomaticKeepAlives = false
2, Tại sao ListView của tôi có khoảng cách với widget bên ngoài
TL: Mặc đinh ListView luôn có padding , để xóa padding bạn cần set EdgeInsets.all(0.0).
Tài liệu tham khảo :
https://medium.com/flutter-community/flutter-listview-and-scrollphysics-a-detailed-look-7f0912df2754