Flutter:吸顶效果
在分页中,实现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});@overrideWidget build(BuildContext context, double shrinkOffset, bool overlapsContent) {// shrinkOffset: 滚动距离// overlapsContent: 是否与其他内容重叠return Container(color: AppTheme.pageBgColor,child: child,);}@overridedouble get maxExtent => 92.w; // 最大高度,已知tab高度72+上下padding:10@overridedouble get minExtent => 92.w; // 最小高度@overridebool 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),],),);}@overrideWidget 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, // 是否进行屏幕适配,默认trueuseDefaultBack: 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();// }@overridevoid 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);
}相关文章:
Flutter:吸顶效果
在分页中,实现tab吸顶。 TDNavBar的screenAdaptation: true, 开启屏幕适配。 该属性已自动对不同手机状态栏高度进行适配。我们只需关注如何实现吸顶。 view import package:ducafe_ui_core/ducafe_ui_core.dart; import package:flutter/material.dart; import p…...
MATLAB语言的数据类型
MATLAB语言的数据类型详解 MATLAB(矩阵实验室)是一种广泛应用于科学计算、数据分析、算法开发及模型构建的高性能语言和环境。MATLAB的强大之处不仅在于其丰富的数学工具和可视化功能,还有其灵活多变的数据类型。这篇文章将详细介绍MATLAB中…...
priority_queue优先队列
目录 1. 最短路径算法(Dijkstra算法) 应用场景: 优先队列的作用: 2. 最小生成树算法(Prim算法) 应用场景: 优先队列的作用: 3. 哈夫曼编码(Huffman Coding&#x…...
HarmonyOS 鸿蒙Next 预览pdf文件
HarmonyOS 鸿蒙Next 预览pdf文件 1、使用filePreview 2、使用web组件 在线pdf(网址是直接下载的,不是直接可以预览的),先下载再预览 import media from ohos.multimedia.media;import web_webview from ohos.web.webview;import …...
vscode开启调试模式,结合Delve调试器调试golang项目详细步骤
1.前期准备 (1).在vs code中的扩展程序中搜索并安装Go扩展程序 (2).安装 Delve 调试器 go install github.com/go-delve/delve/cmd/dlvlatest (3).打开vs code的命令面板,输入Go: Install/Update Tools,并单击该命令执行,安装或更新Go语…...
身份鉴权(PHP)(小迪网络安全笔记~
免责声明:本文章仅用于交流学习,因文章内容而产生的任何违法&未授权行为,与文章作者无关!!! 附:完整笔记目录~ ps:本人小白,笔记均在个人理解基础上整理,…...
【git】-初始git
一、什么是版本控制? 二、Git的安装 三、掌握Linux常用命令 四、Git基本操作 1、提交代码 2、查看历史提交 3、版本回退 一、什么是版本控制? 版本控制是一种用于记录文件或项目内容变化的系统。它通过版本标识和版本历史记录来管理不同版本&#…...
CSS 盒模型
盒模型 CSS盒模型是网页布局的核心概念之一,它描述了网页元素的物理结构和元素内容与周围元素之间的关系。根据W3C规范,每个HTML元素都被视为一个矩形盒子,这个盒子由以下四个部分组成: 内容区(Content areaÿ…...
[0405].第05节:搭建Redis主从架构
Redis学习大纲 一、3主3从的集群配置: 1.1.集群规划 1.分片集群需要的节点数量较多,这里我们搭建一个最小的分片集群,包含3个master节点,每个master包含一个slave节点,结构如下: 2.每组是一主一从&#x…...
6 分布式限流框架
限流的作用 在API对外互联网开放的情况下,是无法控制调用方的行为的。当遇到请求激增或者黑客攻击的情况下,会导致接口占用大量的服务器资源,使得接口响应效率的降低或者超时,更或者导致服务器宕机。 限流是指对应用服务进行限制…...
sosadmin相关命令
sosadmin命令 以下是本人翻译的官方文档,如有不对,还请指出,引用请标明出处。 原本有个对应表可以跳转的,但是CSDN的这个[](#)跳转好像不太一样,必须得用html标签,就懒得改了。 sosadmin help 用法 sosadm…...
关于大数据的基础知识(四)——大数据的意义与趋势
成长路上不孤单😊😊😊😊😊😊 【14后😊///计算机爱好者😊///持续分享所学😊///如有需要欢迎收藏转发///😊】 今日分享关于大数据的基础知识(四&a…...
【EI,Scopus检索 | 往届均已检索见刊】第四届智能系统、通信与计算机网络国际学术会议(ISCCN 2025)
重要信息: 大会官网:更多详情【论文投稿】 截稿时间:以官网信息为准 大会时间:2025年2月21-23日 接受/拒稿通知:投稿后3-5个工作日内 收录检索:EI,Scopus 出版信息: 本会议所有…...
smplx blender插件笔记
目录 liunx安装: liunx安装: pip install smplx 这个创建模型报错 SMPL_blender_addon...
【算法】移除元素
今天讲的是力扣题目的题解: 力扣题目: 72.移除元素 题目描述: 给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素。元素的顺序可能发生改变。然后返回 nums 中与 val 不同的元素的数量。 假设 nums 中不…...
【后端面试总结】设计一个分布式锁需要考虑哪些东西
分布式锁是我们在分布式场景中经常用到的一种技术,在后端面试中也是出镜率很高,那么我们设计分布式锁的时候应该从那几方面去考虑呢 实现分布式锁需要考虑的点 设置超时时间 设置超时时间的目的是为了避免这个场景:进程A拿了锁,…...
awr报告无法生成:常见案例与解决办法
awr报告无法生成:常见案例与解决办法 STATISTICS_LEVEL设置过低数据库打开状态不对主库隐含参数设置错误MMON子进程被SuspendSYS模式统计信息过期WRH$_SQL_PLAN表数据量太大AWR绑定变量信息收集超时撞上数据库Bug 9040676STATISTICS_LEVEL设置过低 STATISTICS_LEVEL设置为BAS…...
Hadoop 生态之 kerberos
参考链接 https://winway.github.io/2022/04/02/kerberos-ranger/ https://ieevee.com/tech/2016/06/22/ranger-2.html kerberos解决”who are you“的问题 ranger解决”what you can do“的问题 LDAP 轻型目录访问协议(英文:Lightweight Director…...
【文件I/O】文件持久化
这篇文章详细讲解的是 理解在Linux操作系统中输入/输出(I/O)编程与文件操作的关系。 在计算机编程中,输入/输出编程(I/O 编程) 是一个重要的概念,指的是通过程序与外部世界(如用户输入、文件、…...
USB学习——基本概念
文章目录 USB(Universal Serial Bus)概述USB系统的描述USB总线传输方式USB的拓扑结构 USB的连接模型USB控制器及分类USB描述符USB 端点USB枚举过程USB 四种传输类型USB 事务批量传输(Bulk)中断传输(Interrupt)等时传输(Isochronous)控制传输(Control)端点…...
IDEA运行Tomcat出现乱码问题解决汇总
最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…...
国防科技大学计算机基础课程笔记02信息编码
1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制,因此这个了16进制的数据既可以翻译成为这个机器码,也可以翻译成为这个国标码,所以这个时候很容易会出现这个歧义的情况; 因此,我们的这个国…...
日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻
在如今就业市场竞争日益激烈的背景下,越来越多的求职者将目光投向了日本及中日双语岗位。但是,一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧?面对生疏的日语交流环境,即便提前恶补了…...
Vue记事本应用实现教程
文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展:显示创建时间8. 功能扩展:记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...
8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂
蛋白质结合剂(如抗体、抑制肽)在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上,高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术,但这类方法普遍面临资源消耗巨大、研发周期冗长…...
关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案
问题描述:iview使用table 中type: "index",分页之后 ,索引还是从1开始,试过绑定后台返回数据的id, 这种方法可行,就是后台返回数据的每个页面id都不完全是按照从1开始的升序,因此百度了下,找到了…...
2.Vue编写一个app
1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...
sqlserver 根据指定字符 解析拼接字符串
DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...
【AI学习】三、AI算法中的向量
在人工智能(AI)算法中,向量(Vector)是一种将现实世界中的数据(如图像、文本、音频等)转化为计算机可处理的数值型特征表示的工具。它是连接人类认知(如语义、视觉特征)与…...
vue3 定时器-定义全局方法 vue+ts
1.创建ts文件 路径:src/utils/timer.ts 完整代码: import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...
