在分页中,实现tab吸顶。
TDNavBar的screenAdaptation: true, 开启屏幕适配。
该属性已自动对不同手机状态栏高度进行适配。我们只需关注怎样实现吸顶。


view
- import 'package:ducafe_ui_core/ducafe_ui_core.dart';
- import 'package:flutter/material.dart';
- import 'package:get/get.dart';
- import 'package:pull_to_refresh_flutter3/pull_to_refresh_flutter3.dart';
- import 'package:tdesign_flutter/tdesign_flutter.dart';
- import 'package:xiaoshukeji/common/index.dart';
- import 'index.dart';
- // 1. SliverPersistentHeaderDelegate:必须实现的抽象类
- class _StickyTabBarDelegate extends SliverPersistentHeaderDelegate {
- final Widget child;
- _StickyTabBarDelegate({required this.child});
- @override
- Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
- // shrinkOffset: 滚动距离
- // overlapsContent: 是否与其他内容重叠
- return Container(
- color: AppTheme.pageBgColor,
- child: child,
- );
- }
- @override
- double get maxExtent => 92.w; // 最大高度,已知tab高度72+上下padding:10
- @override
- double get minExtent => 92.w; // 最小高度
- @override
- bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) => true;
- }
- class RankingPage extends GetView<RankingController> {
- const RankingPage({super.key});
- // 头部皇冠位置
- Widget _buildHeader() {
- return <Widget>[
- ].toRow()
- .card(color: AppTheme.pageBgColor)
- .tight(width: 750.w,height: 300.w,);
- }
- // tab,可吸顶
- Widget _buildTab() {
- return <Widget>[
- <Widget>[
- TextWidget.body('日榜', size: 28.sp, weight: FontWeight.w600, color: AppTheme.textColorfff),
- ].toRow(mainAxisAlignment: MainAxisAlignment.center)
- .card(color: AppTheme.primaryYellow)
- .tight(width: 336.w,height: 72.w,),
- <Widget>[
- TextWidget.body('总榜', size: 28.sp, weight: FontWeight.w600, color: AppTheme.textColor6a7),
- ].toRow(mainAxisAlignment: MainAxisAlignment.center)
- .card(color: AppTheme.navBarBgColor)
- .tight(width: 336.w,height: 72.w,),
- ].toRow(mainAxisAlignment: MainAxisAlignment.spaceBetween);
- }
- // 数据列表
- Widget _buildDataList() {
- return SliverList(
- delegate: SliverChildBuilderDelegate(
- (context, index) {
- return <Widget>[]
- .toRow()
- .paddingHorizontal(30.w)
- .card(color: AppTheme.blockBgColor)
- .tight(
- width: 690.w,
- height: 120.w,
- )
- .marginOnly(bottom: 20.w);
- },
- childCount: 20,
- ),
- );
- }
- // 主视图
- Widget _buildView() {
- return SmartRefresher(
- controller: controller.refreshController,
- enablePullUp: true,
- onRefresh: controller.onRefresh,
- onLoading: controller.onLoading,
- footer: const SmartRefresherFooterWidget(),
- header: const SmartRefresherHeaderWidget(),
- child: CustomScrollView(
- slivers: [
- // 头部
- _buildHeader().sliverToBoxAdapter().sliverPaddingHorizontal(30.w),
-
- // 2. SliverPersistentHeader:实现吸顶的核心组件
- SliverPersistentHeader(
- pinned: true, // 设置为 true 实现吸顶
- delegate: _StickyTabBarDelegate(
- child: Container(
- padding: EdgeInsets.symmetric(horizontal: 30.w, vertical: 10.w),
- child: _buildTab(),
- ),
- ),
- ),
-
- // 列表内容
- _buildDataList().sliverPaddingHorizontal(30.w),
- ],
- ),
- );
- }
- @override
- Widget build(BuildContext context) {
- return GetBuilder<RankingController>(
- init: RankingController(),
- id: "ranking",
- builder: (_) {
- return Scaffold(
- backgroundColor: AppTheme.pageBgColor, // 自定义颜色
- appBar: const TDNavBar(
- height: 0,
- titleColor: AppTheme.textColorfff,
- titleFontWeight: FontWeight.w600,
- backgroundColor: AppTheme.pageBgColor,
- screenAdaptation: true, // 是否进行屏幕适配,默认true
- useDefaultBack: false,
- ),
- body: _buildView(),
- );
- },
- );
- }
- }
复制代码 controller
- import 'package:get/get.dart';
- import 'package:pull_to_refresh_flutter3/pull_to_refresh_flutter3.dart';
- class RankingController extends GetxController {
- RankingController();
- List items = [];
- /*
- * 分页
- * refreshController:分页控制器
- * _page:分页
- * _limit:每页条数
- * _loadNewsSell:拉取数据(是否刷新)
- * onLoading:上拉加载新商品
- * onRefresh:下拉刷新
- * */
- final RefreshController refreshController = RefreshController(
- initialRefresh: true,
- );
- // int _page = 1;
- // int _limit = 20;
- Future<bool> _loadNewsSell(bool isRefresh) async {
- return false;
- // var result = await ProductApi.products(ProductsReq(
- // page:isRefresh ? 1:_page,
- // prePage:_limit
- // ));
- // if(isRefresh){
- // _page = 1;
- // items.clear();
- // }
- // if(result.isNotEmpty){
- // _page++;
- // items.addAll(result);
- // }
- // // 是否是空
- // return result.isEmpty;
- }
- // 上拉载入新商品
- void onLoading() async {
- if (items.isNotEmpty) {
- try {
- // 拉取数据是否为空 ? 设置暂无数据 : 加载完成
- var isEmpty = await _loadNewsSell(false);
- isEmpty
- ? refreshController.loadNoData()
- : refreshController.loadComplete();
- } catch (e) {
- refreshController.loadFailed(); // 加载失败
- }
- } else {
- refreshController.loadNoData(); // 设置无数据
- }
- update(["ranking"]);
- }
- // 下拉刷新
- void onRefresh() async {
- try {
- await _loadNewsSell(true);
- refreshController.refreshCompleted();
- } catch (e) {
- refreshController.refreshFailed();
- }
- update(["ranking"]);
- }
- _initData() {
- update(["ranking"]);
- }
- void onTap() {}
- // @override
- // void onInit() {
- // super.onInit();
- // }
- @override
- void onReady() {
- super.onReady();
- _initData();
- }
- // @override
- // void onClose() {
- // super.onClose();
- // }
- }
复制代码 纪录tab切换
- int currentTab = 0; // 当前选中的tab索引
- // tab切换方法
- void switchTab(int index) {
- if (currentTab == index) return;
- currentTab = index;
- items.clear();// 切换tab时重置列表数据
- refreshController.requestRefresh();
- update(["ranking"]);
- }
- // tab切换
- Widget _buildTab() {
- return <Widget>[
- <Widget>[
- TextWidget.body('日榜', size: 28.sp, weight: FontWeight.w600, color: controller.currentTab == 0 ? AppTheme.textColorfff : AppTheme.textColor646),
- ].toRow(mainAxisAlignment: MainAxisAlignment.center)
- .card(color: controller.currentTab == 0 ? AppTheme.primaryYellow : AppTheme.navBarBgColor)
- .tight(width: 336.w,height: 72.w,).onTap(() {
- controller.switchTab(0);
- }),
- <Widget>[
- TextWidget.body('总榜', size: 28.sp, weight: FontWeight.w600, color: controller.currentTab == 1 ? AppTheme.textColorfff : AppTheme.textColor646),
- ].toRow(mainAxisAlignment: MainAxisAlignment.center)
- .card(color: controller.currentTab == 1 ? AppTheme.primaryYellow : AppTheme.navBarBgColor )
- .tight(width: 336.w,height: 72.w,).onTap(() {
- controller.switchTab(1);
- }),
- ].toRow(mainAxisAlignment: MainAxisAlignment.spaceBetween);
- }
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |