Flutter CustomScrollView 效果-顶栏透明与标签栏吸顶
CustomScrollView 效果
1. 关键组件
CustomScrollView
, SliverOverlapAbsorber
, SliverPersistentHeader
2. 关键内容 TLDR
SliverOverlapAbsorber
包住pinned
为 true 的组件 可以被CustomScrollView
忽略高度。
以下的全部内容的都为了阐述上面这句话。初阶 Flutter 开发知道这句话或许可以节省数天研究时间。
pinned
为 true 的组件:SliverPersistentHeader
和 SliverAppBar
被 CustomScrollView
忽略高度可以使的其他的 Sliver
组件与 pinned
为 true
的组件有重叠效果
3. 正文
先进行定义 TopBar:顶部栏, TabBar:吸顶的标签栏。 对上说效果进行说明: 刚进入页面时,TopBar 下是透明的,一般业务上用来显示 banner 或者重要的广告。 向上滑动页面,TabBar 滑动到顶部时吸顶 并且位于 TopBar 以下。 代码的结构如下
CustomScrollView(controller: _controller,slivers: <Widget>[/// 顶部栏,固定在顶部SliverOverlapAbsorber(handle: SliverOverlapAbsorberHandle(),sliver: SliverAppBar(pinned: true:...)),/// 比如 Banner,金刚区等SliverToBoxAdapter(child: Image.asset("./assets/images/sky.webp",fit: BoxFit.cover,),),/// 其他一些 Sliver 组件...///吸顶的标签栏SliverPersistentHeader(pinned: true,delegate: TabBarDelegate()),/// 列表SliverList(),],
)
在这里例子中,CutomScrollView
会忽略 SliverOverlapAbsorber
组件高度,使得之后的组件计算开始布局的位置从SliverOverlapAbsorber
的上边缘开始计算。这样当 TopBar 透明时可以看到完整的 Banner 大图 。
如何使得 TabBar 吸顶并且位于 TopBar 下面呢,可以使用 SliverAppBar
作为 TopBar, 使用 SliverPersistentHeader
作为 TabBar。将两个组件中的 pinned
属性都设置为 true
之后,当页面上滑时当 TabBar 滑到 TopBar 下方时便会固定住不再向上滑动。
换个便于记忆的简单说法是,在 CustomScrollView
中,如果想要忽略高度用 SliverOverlapAbsorber
,想要吸顶就用 SliverPersistentHeader
。
TopBar 底部用到大图,为什么不用 SliverAppBar
的 flexibleSpace
属性?
使用 SliverAppBar 的特性需要修改属性较多,而且把 顶部 Banner 与 SliverAppBar 混在一起并不优雅。如果只能用 flexbleSpace 实现可以如此
SliverAppBar(pinned: true,expandedHeight: 200,title: TopBar()flexibleSpace: FlexibleSpaceBar(collapseMode: CollapseMode.pin,background: Banner(),),
)
TabBar 怎么吸顶的?
TabBar 之所以能吸顶是使用的 SliverPersistentHeader
中使用了 RenderSliverPinnedPersistentHeader
。
class RenderSliverPinnedPersistentHeader{void performLayout() {
...geometry = SliverGeometry(scrollExtent: maxExtent,paintOrigin: constraints.overlap,paintExtent: math.min(childExtent, effectiveRemainingPaintExtent),layoutExtent: layoutExtent,maxPaintExtent: maxExtent + stretchOffset,maxScrollObstructionExtent: minExtent,cacheExtent: layoutExtent > 0.0 ? -constraints.cacheOrigin + layoutExtent : layoutExtent,hasVisualOverflow: true, // Conservatively say we do have overflow to avoid complexity.);}...
}
吸顶关键是设置 paintOrigin
属性。paintOrigin
注释如下
/// The visual location of the first visible part of this sliver relative to/// its layout position.
官方的注释说的比较严谨且抽象,我尝试解释下 直译是 sliver 的可见位置相对于布局位置。布局位置可以理解为 sliver 占据的空间,可见位置就是其绘制的位置。如果 paintOrigin
为 0,那么可见位置就是布局位置,就像普通的不吸顶的 sliver 一样。 paintOrigin: constraints.overlap
意为从距离布局位置顶部 constraints.overlap
的距离开始绘制。constraints.overlap
是两个页面重叠的距离,如果当前吸顶组件的上面没有其他可吸顶组件,则这个值就是 0,如何之前有其他的吸顶组件,比如 TopBar 也是吸顶组件,这个值就与 TopBar 的高度相同,如是 TabBar 可以悬停在 TopBar 下面。有时学习为了解释一个概念,又会引入了另外一个新概念,导致复杂度成倍增加,有时甚至会引入几十个甚至几百个新概念,尽管如此,坚持下去,才能真正理解知识,而不是原地空转。
有个 SliverPhysicalParentData.paintOffset
属性 与 paintOrigin 类似的概念也对 sliver 组件的绘制位置有影响。在 不吸顶的组件(如 SliverToBoxAdapter
)中 paintOffset
为 SliverConstraint.scrollOffset
在 可以悬停吸顶的组件 SliverPersistentHeader
中 paintOffset
是 Offset(0, 0)
final SliverPhysicalParentData childParentData = child!.parentData! as SliverPhysicalParentData;
childParentData.paintOffset = Offset(0, 0);
为什么 SliverOverlapAbsorber
高度会被忽略?
SliverOverlapAbsorber
实际渲染的是 RenderSliverOverlapAbsorber
。在 RenderSliverOverlapAbsorber.performLayout
中设定高度代码如下
child!.layout(constraints, parentUsesSize: true);
final SliverGeometry childLayoutGeometry = child!.geometry!;
geometry = childLayoutGeometry.copyWith(scrollExtent: childLayoutGeometry.scrollExtent - childLayoutGeometry.maxScrollObstructionExtent,layoutExtent: math.max(0, childLayoutGeometry.paintExtent - childLayoutGeometry.maxScrollObstructionExtent),
);
可以看到 SliverOverlapAbsorber
的高度依赖于 child
的信息 scrollExtent - maxScrollObstructionExtent
。
child
是什么?当 SliverOverlapAbsorber
中包含的 SliverAppBar
属性 pinned
设置为 true
时,child
实际为 RenderSliverPinnedPersistentHeader
void performLayout() {...geometry = SliverGeometry(scrollExtent: maxExtent,paintOrigin: constraints.overlap,paintExtent: math.min(childExtent, effectiveRemainingPaintExtent),layoutExtent: layoutExtent,maxPaintExtent: maxExtent + stretchOffset,maxScrollObstructionExtent: minExtent,cacheExtent: layoutExtent > 0.0 ? -constraints.cacheOrigin + layoutExtent : layoutExtent,hasVisualOverflow: true, // Conservatively say we do have overflow to avoid complexity.);}
可以看到 scrollExtent
是 maxExtent
, maxScrollObstructionExtent
是 minExtent
,当 SliverAppBar
不设置 expandedHeight
时 maxExtent
与 minExtent
相等,最终 SliverOverlapAbsorber
中的 geometry
中 scrollExtent
和 layoutExtent
为 0。从而 CustomScrollView 忽略了 SliverOverlapAbsorber
高度。 注意 只有 SliverOverlapAbsorber 包含的 SliverAppBar
组件 pinned=true
时才会忽略 SliverAppBar 的高度,并且忽略的部分依据 maxExtent
和 minExtent
相等时才完全忽略。
4. 结语
重要内容总结为一句话和一些 限定语
-
SliverOverlapAbsorber
可以让CustomScrollView
忽略 其包含的固定组件高度 -
SliverOverlapAbsorber
包含的SliverAppBar
需要设置为pinned=true
-
SliverAppBar
的maxExtent
和minExtent
相等时 整个SliverAppBar
的高度都会被忽略
记住了组件的作用在用到时就可以快速完成大部分工作了,再了解了组件原理就可以更好的完成工作了,当效果偏离预想时也可以纠偏找到正确的思路。
5. 团队介绍
「三翼鸟数字化技术平台-商城」负责搭建门店数字化转型工具,包括:海尔智家体验店小程序、三翼鸟工作台APP、商家中心等产品形态,通过数字化工具,实现门店的用户上平台、交互上平台、交易上平台、交付上平台,从而助力海尔专卖店的零售转型,并实现三翼鸟店的场景创新。
相关文章:

Flutter CustomScrollView 效果-顶栏透明与标签栏吸顶
CustomScrollView 效果 1. 关键组件 CustomScrollView, SliverOverlapAbsorber, SliverPersistentHeader 2. 关键内容 TLDR SliverOverlapAbsorber 包住 pinned为 true 的组件 可以被CustomScrollView 忽略高度。 以下的全部内容的都为了阐述上面这句话。初阶 Flutter 开发知…...
【新手入门软件测试--该如何分辨前后端问题及如何定位日志--前后端问题分辨与日志定位查询问题】
前后端问题分辨与日志定位查询 一、前端问题1. 页面无法加载2. 样式错乱3. API请求失败4. 数据格式错误5. 跨域请求问题 二、后端问题6. 表单验证失败7. 数据库连接失败8. 请求超时9. 权限问题10. JavaScript运行错误 三、日志查询的方法1. 查看日志文件2. 过滤关键字3. 实时查…...

【Java Web】DAO模式及单例模式(含代码示例)
文章目录 JDBC封装DAO模式实体类DAO接口DAO实现类数据源配置基础DAO类业务逻辑层 单例模式饿汉式懒汉式 JDBC封装 JDBC(Java Database Connectivity)封装是一种将 JDBC 的基本操作和常见的数据库访问逻辑封装成易于使用的工具类或框架的方法。这样做的目…...

深入探讨SEO分析技巧助力网站流量提升
内容概要 在当前的数字化时代,SEO分析的重要性不言而喻。它是提升网站流量的关键工具,帮助站长有效地优化网站内容和结构。通过系统的SEO分析,站长可以掌握用户搜索行为和需求,从而制定出更具针对性的内容策略。例如,…...

Chrome 130 版本开发者工具(DevTools)更新内容
Chrome 130 版本开发者工具(DevTools)更新内容 一、网络(Network)面板更新 1. 重新定义网络过滤器 网络面板获新增了一些过滤条件,这些过滤条件是根据反馈重新设计的,特定于类型的过滤条件保持不变&…...

深度学习基础知识-残差网络ResNet
目录 一、ResNet 的核心思想:残差学习(Residual Learning) 二、ResNet 的基本原理 三、ResNet 网络结构 1. 残差块(Residual Block) ResNet 的跳跃连接类型 2. 网络结构图示 四、ResNet 的特点和优势 五、ResNe…...
Linux云计算个人学习总结(二)
高级文件系统 一、RSYNC概述 1、作用:快速的文件复制工具(支持本地和远程),以及删除、查看等基本功能。 2、特点:支持实时(inotify、sersync)的增量备份工具3、模式:检查模式&#…...
Java入门(7)--网络编程
Java网络编程:构建网络应用的基石 🌐 🎯 掌握Java网络编程,打造强大的网络应用! 在上一篇文章中,我们探讨了Java的I/O操作和反射机制。今天,让我们深入学习Java网络编程,了解如何构建…...
[思考记录]思维局限,以为懂了
最近配合整理一些内容,找到较早期的某些产品设计资料在翻阅回顾。在这次回顾过程中,发现当时自己的理解存在很多局限。 以资源体系的设计为例,那时自认为已经“懂了”,对相关的概念、作用关系、组成及实现等都有一定的了解&#x…...
力扣题目解析--最长公共前缀
题目 编写一个函数来查找字符串数组中的最长公共前缀。 如果不存在公共前缀,返回空字符串 ""。 示例 1: 输入:strs ["flower","flow","flight"] 输出:"fl"示例 2ÿ…...
不画饼——研究生学习和赚钱的平衡点
在现代社会中,年轻人面临着学习和赚钱之间的矛盾。尤其是在经济压力日益增大的背景下,如何在这两者之间找到合适的平衡点,成为了许多学生和职场新人面临的重要问题。本文将探讨在何种情况下应该听从老师的建议,专注于学习…...

华为实时视频使用FLV播放RTSP流
import flvjs from ‘flv.js’; 安装flv <video style"width:100%;height:100%;" ref"videoHWRef" ></video>// src 华为rtsp流 rtsp://admin:Huaweivideo10.10.8.151:554/xxx/trackID1// url 需要后端提供视频源地址playVideo() {if (fl…...

JAVA设计模式之【建造者模式】
1 定义 建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 2 类图 产品类(Product):表示被创建的复杂…...

【jvm】为什么Xms和Xmx的值通常设置为相同的?
目录 1. 说明2. 避免性能开销3. 提升稳定性4. 简化配置5. 优化垃圾收集6. 获取参数6.1 代码示例6.2 结果示例 1. 说明 1.-Xms 和 -Xmx 参数分别用于设置堆内存的初始大小(最小值)和最大大小。2.在开发环境中,开发人员可能希望快速启动应用程…...
windows查看net网络监听端口命令和工具(ipconfig、netstat、tasklist、TCPView)
文章目录 使用命令提示符(CMD)查看网络连接和配置使用 netstat 命令查看监听端口查看特定的端口查看TCP监听端口tasklist查看对应进程ID的程序Get-NetTCPConnection 命令使用 TCPView工具使用命令提示符(CMD) 查看网络连接和配置 ipconfig :显示所有网络 适配器的当前 TC…...

JAVA-数据结构- 二叉搜索树
1.搜索树 前面我们已经使用C语言学习完了二叉树,懂得了一些二叉树的基本性质已经实现方法 https://mp.csdn.net/mp_blog/creation/editor/139572374,本文我们来一起进行二叉树的衍生-二叉搜索树 1.1 概念 二叉搜索树又称二叉排序树,它或者是…...
深入研究 RAG 流程中的关键组件
我们已经看到了整个RAG流程,并获得了第一手的实践经验,您可能会对RAG流程中一些组件的使用和目的存在很多疑惑,比如RunnablePassthrough。在本节中,我们将进一步了解这些关键组件。 RAG的核心模型思想是将一个复杂的任务分解为多…...
新手如何学习python并快速成为高手
英雄Python入门到精通链接:https://pan.quark.cn/s/57162ec366a9 学习Python作为新手,有以下几个步骤: 学习基本概念和语法:首先,你需要学习Python的基本概念和语法。可以通过在线教程、书籍或者视频教程来学习。了解…...

Linux历史命令history增加执行时间显示
Centos系统默认历史命令显示如下 为了更好的溯源,获取执行命令的准确时间,需要增加一些配置 设置环境变量 vim /etc/profile 在最下面添加以下环境配置 export HISTTIMEFORMAT"%Y-%m-%d %H:%M:%S " 立即刷新该环境变量 source /etc/pro…...

从 vue 源码看问题 — 你知道 Hook Event 吗?
前言 在之前的几篇文章中,都有提到 vue 中调用生命周期钩子时是通过 callHook() 方法进行调用的,比如在初始化篇章中调用 beforeCreate 和 created 生命周期钩子方式如下: 那么接下来一起来了解下到底什么是 Hook Event ? Hook Event 是什…...

装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...
Vue记事本应用实现教程
文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展:显示创建时间8. 功能扩展:记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...
java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别
UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)
骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术,它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton):由层级结构的骨头组成,类似于人体骨骼蒙皮 (Mesh Skinning):将模型网格顶点绑定到骨骼上,使骨骼移动…...
OpenLayers 分屏对比(地图联动)
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能,和卷帘图层不一样的是,分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...
Element Plus 表单(el-form)中关于正整数输入的校验规则
目录 1 单个正整数输入1.1 模板1.2 校验规则 2 两个正整数输入(联动)2.1 模板2.2 校验规则2.3 CSS 1 单个正整数输入 1.1 模板 <el-formref"formRef":model"formData":rules"formRules"label-width"150px"…...

基于SpringBoot在线拍卖系统的设计和实现
摘 要 随着社会的发展,社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 在线拍卖系统,主要的模块包括管理员;首页、个人中心、用户管理、商品类型管理、拍卖商品管理、历史竞拍管理、竞拍订单…...
腾讯云V3签名
想要接入腾讯云的Api,必然先按其文档计算出所要求的签名。 之前也调用过腾讯云的接口,但总是卡在签名这一步,最后放弃选择SDK,这次终于自己代码实现。 可能腾讯云翻新了接口文档,现在阅读起来,清晰了很多&…...
Redis:现代应用开发的高效内存数据存储利器
一、Redis的起源与发展 Redis最初由意大利程序员Salvatore Sanfilippo在2009年开发,其初衷是为了满足他自己的一个项目需求,即需要一个高性能的键值存储系统来解决传统数据库在高并发场景下的性能瓶颈。随着项目的开源,Redis凭借其简单易用、…...

Elastic 获得 AWS 教育 ISV 合作伙伴资质,进一步增强教育解决方案产品组合
作者:来自 Elastic Udayasimha Theepireddy (Uday), Brian Bergholm, Marianna Jonsdottir 通过搜索 AI 和云创新推动教育领域的数字化转型。 我们非常高兴地宣布,Elastic 已获得 AWS 教育 ISV 合作伙伴资质。这一重要认证表明,Elastic 作为 …...