14.9 拉取商品 sliver 滚动
 
实现步骤:
第 1 步:商品 api
接口参数

第 2 步:控制器
lib/pages/search/search_filter/controller.dart
| 12
 3
 4
 
 | int? tagId = Get.arguments["tagId"] ?? "";
 
 List<ProductModel> items = [];
 
 | 
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 
 | final RefreshController refreshController = RefreshController(
 initialRefresh: true,
 );
 
 int _page = 1;
 
 final int _limit = 20;
 
 
 final String _orderBy = "id";
 
 
 final String _order = "desc";
 
 | 
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 
 | 
 Future<bool> _loadSearch(bool isRefresh) async {
 
 var result = await ProductApi.products(ProductsReq(
 
 page: isRefresh ? 1 : _page,
 
 prePage: _limit,
 
 tag: "$tagId",
 
 orderby: _orderBy,
 
 order: _order,
 
 minPrice: "${priceRange[0]}",
 maxPrice: "${priceRange[1]}",
 ));
 
 
 if (isRefresh) {
 _page = 1;
 items.clear();
 }
 
 
 if (result.isNotEmpty) {
 _page++;
 items.addAll(result);
 
 items.addAll(result);
 items.addAll(result);
 items.addAll(result);
 }
 
 
 return result.isEmpty;
 }
 
 | 
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 
 | void onLoading() async {
 if (items.isNotEmpty) {
 try {
 
 var isEmpty = await _loadSearch(false);
 
 if (isEmpty) {
 
 refreshController.loadNoData();
 } else {
 
 refreshController.loadComplete();
 }
 } catch (e) {
 
 refreshController.loadFailed();
 }
 } else {
 
 refreshController.loadNoData();
 }
 update(["filter_products"]);
 }
 
 | 
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 
 | void onRefresh() async {
 try {
 await _loadSearch(true);
 
 refreshController.refreshCompleted();
 } catch (error) {
 
 refreshController.refreshFailed();
 }
 update(["filter_products"]);
 }
 
 | 
| 12
 3
 4
 5
 
 | void onFilterApplyTap() {
 refreshController.requestRefresh();
 Get.back();
 }
 
 | 
| 12
 3
 4
 5
 6
 
 | @overridevoid onClose() {
 super.onClose();
 
 refreshController.dispose();
 }
 
 | 
第 3 步:FilterView 视图
点击应用的时候,刷新数据
lib/pages/search/search_filter/widgets/filter_view.dart
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 
 | Widget _buildView() {return <Widget>[
 ...
 
 
 const Divider(),
 ButtonWidget.primary(
 LocaleKeys.commonBottomApply.tr,
 onTap: controller.onFilterApplyTap,
 ).tight(
 width: 75,
 height: 25,
 ),
 
 ...
 
 | 
第 4 步:视图
lib/pages/search/search_filter/view.dart
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 
 | Widget _buildListView() {
 return GetBuilder<SearchFilterController>(
 id: "filter_products",
 builder: (_) {
 return controller.items.isEmpty
 ?
 
 const PlaceholdWidget().sliverBox
 :
 
 SliverGrid.extent(
 maxCrossAxisExtent: 120,
 mainAxisSpacing: AppSpace.listRow,
 crossAxisSpacing: AppSpace.listItem,
 childAspectRatio: 0.7,
 children: controller.items.map((product) {
 return ProductItemWidget(
 product,
 imgHeight: 117.w,
 );
 }).toList(),
 );
 },
 );
 }
 
 | 
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 
 | Widget _buildView() {
 return <Widget>[
 
 _buildFilterBar(),
 
 
 SmartRefresher(
 controller: controller.refreshController,
 enablePullUp: true,
 onRefresh: controller.onRefresh,
 onLoading: controller.onLoading,
 footer: const SmartRefresherFooterWidget(),
 child: CustomScrollView(
 slivers: [
 _buildListView().sliverPaddingHorizontal(AppSpace.button),
 ],
 ),
 ).expanded(),
 ].toColumn();
 }
 
 | 
这里是课程设计需要,SmartRefresher 包裹 sliver 组件。
SmartRefresher 包含 GridList 并嵌入Column 中进行上下拉操作,需要用到 sliver 来衔接。
提交代码到 git