9.8 新商品栏、上下拉刷新
实现步骤:
第 1 步:安装插件 pull_to_refresh
| 1
 | flutter pub add pull_to_refresh
 | 
第 2 步:main 配置插件
lib/main.dart
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 
 | class MyApp extends StatelessWidget {const MyApp({Key? key}) : super(key: key);
 
 @override
 Widget build(BuildContext context) {
 return ScreenUtilInit(
 ...
 builder: () {
 return RefreshConfiguration(
 headerBuilder: () => const ClassicHeader(),
 footerBuilder: () => const ClassicFooter(),
 hideFooterWhenNotFull: true,
 headerTriggerDistance: 80,
 maxOverScrollExtent: 100,
 footerTriggerDistance: 150,
 child: GetMaterialApp(
 title: 'Flutter Demo',
 
 ...
 ),
 );
 },
 );
 }
 
 | 
第 3 步:控制器
lib/pages/goods/home/controller.dart
| 12
 3
 4
 5
 6
 7
 8
 
 | final RefreshController refreshController = RefreshController(
 initialRefresh: true,
 );
 
 int _page = 1;
 
 final int _limit = 20;
 
 | 
| 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
 
 | 
 Future<bool> _loadNewsSell(bool isRefresh) async {
 
 var result = await ProductApi.products(ProductsReq(
 
 page: isRefresh ? 1 : _page,
 
 prePage: _limit,
 ));
 
 
 if (isRefresh) {
 _page = 1;
 newProductProductList.clear();
 }
 
 
 if (result.isNotEmpty) {
 
 _page++;
 
 
 newProductProductList.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 (newProductProductList.isNotEmpty) {
 try {
 
 var isEmpty = await _loadNewsSell(false);
 
 if (isEmpty) {
 
 refreshController.loadNoData();
 } else {
 
 refreshController.loadComplete();
 }
 } catch (e) {
 
 refreshController.loadFailed();
 }
 } else {
 
 refreshController.loadNoData();
 }
 update(["home_news_sell"]);
 }
 
 | 
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | void onRefresh() async {
 try {
 await _loadNewsSell(true);
 refreshController.refreshCompleted();
 } catch (error) {
 refreshController.refreshFailed();
 }
 update(["home_news_sell"]);
 }
 
 | 
| 12
 3
 4
 5
 6
 
 | @overridevoid onClose() {
 super.dispose();
 
 refreshController.dispose();
 }
 
 | 
第 4 步:刷新底部组件
lib/common/components/refresher.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
 27
 28
 29
 30
 31
 
 | import 'package:flutter/cupertino.dart';import 'package:pull_to_refresh/pull_to_refresh.dart';
 
 import '../index.dart';
 
 
 class SmartRefresherFooterWidget extends StatelessWidget {
 
 final double? height;
 
 
 final double? iconSize;
 
 const SmartRefresherFooterWidget({
 Key? key,
 this.iconSize,
 this.height,
 }) : super(key: key);
 
 @override
 Widget build(BuildContext context) {
 return ClassicFooter(
 height: height ?? 60 + MediaQuery.of(context).padding.bottom + 30,
 loadingIcon: const CupertinoActivityIndicator().tight(
 width: iconSize ?? 25,
 height: iconSize ?? 25,
 ),
 outerBuilder: (child) => child.center().height(height ?? 60),
 );
 }
 }
 
 | 
第 5 步:视图
lib/pages/goods/home/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
 27
 28
 
 | Widget _buildNewSell() {
 return GetBuilder<HomeController>(
 id: "home_news_sell",
 builder: (_) {
 return SliverGrid(
 delegate: SliverChildBuilderDelegate(
 (BuildContext context, int position) {
 var product = controller.newProductProductList[position];
 return ProductItemWidget(
 product,
 imgHeight: 170.w,
 );
 },
 childCount: controller.newProductProductList.length,
 ),
 gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
 crossAxisCount: 2,
 mainAxisSpacing: AppSpace.listRow,
 crossAxisSpacing: AppSpace.listItem,
 childAspectRatio: 0.8,
 ),
 )
 .sliverPadding(bottom: AppSpace.page)
 .sliverPaddingHorizontal(AppSpace.page);
 },
 );
 }
 
 | 
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 
 | Widget _buildView() {
 return CustomScrollView(
 slivers: [
 ...
 
 
 
 controller.newProductProductList.isNotEmpty
 ? BuildListTitle(
 title: LocaleKeys.gHomeNewProduct.tr,
 onTap: () => controller.onAllTap(false),
 ).sliverToBoxAdapter().sliverPaddingHorizontal(AppSpace.page)
 : const SliverToBoxAdapter(),
 
 _buildNewSell(),
 ],
 );
 }
 
 | 
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 
 | @overrideWidget build(BuildContext context) {
 return GetBuilder<HomeController>(
 init: Get.find<HomeController>(),
 id: "home",
 builder: (_) {
 return Scaffold(
 appBar: _buildAppBar(),
 body: SmartRefresher(
 controller: controller.refreshController,
 enablePullUp: true,
 onRefresh: controller.onRefresh,
 onLoading: controller.onLoading,
 footer: const SmartRefresherFooterWidget(),
 child: _buildView(),
 ),
 );
 },
 );
 }
 
 | 
SmartRefresher 实现上下拉效果,child 子元素必须是一个 ScrollView 可滚动组件
提交代码到 git