Flutter CustomScrollView 效果-顶栏透明与标签栏吸顶

CustomScrollView 效果

1. 关键组件

CustomScrollView, SliverOverlapAbsorber, SliverPersistentHeader

2. 关键内容 TLDR

SliverOverlapAbsorber 包住 pinned为 true 的组件 可以被CustomScrollView 忽略高度。

以下的全部内容的都为了阐述上面这句话。初阶 Flutter 开发知道这句话或许可以节省数天研究时间。

pinned为 true 的组件:SliverPersistentHeaderSliverAppBar

CustomScrollView 忽略高度可以使的其他的 Sliver 组件与 pinnedtrue 的组件有重叠效果

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 底部用到大图,为什么不用 SliverAppBarflexibleSpace 属性?

使用 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 )中 paintOffsetSliverConstraint.scrollOffset在 可以悬停吸顶的组件 SliverPersistentHeaderpaintOffsetOffset(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.);}

可以看到 scrollExtentmaxExtentmaxScrollObstructionExtentminExtent,当 SliverAppBar 不设置 expandedHeightmaxExtentminExtent 相等,最终 SliverOverlapAbsorber 中的 geometryscrollExtentlayoutExtent 为 0。从而 CustomScrollView 忽略了 SliverOverlapAbsorber 高度。 注意 只有 SliverOverlapAbsorber 包含的 SliverAppBar组件 pinned=true 时才会忽略 SliverAppBar 的高度,并且忽略的部分依据 maxExtentminExtent 相等时才完全忽略。

4. 结语

重要内容总结为一句话和一些 限定语

  • SliverOverlapAbsorber 可以让 CustomScrollView 忽略 其包含的固定组件高度

  • SliverOverlapAbsorber 包含的 SliverAppBar 需要设置为 pinned=true

  • SliverAppBarmaxExtentminExtent 相等时 整个 SliverAppBar 的高度都会被忽略

记住了组件的作用在用到时就可以快速完成大部分工作了,再了解了组件原理就可以更好的完成工作了,当效果偏离预想时也可以纠偏找到正确的思路。

5. 团队介绍

三翼鸟数字化技术平台-商城」负责搭建门店数字化转型工具,包括:海尔智家体验店小程序、三翼鸟工作台APP、商家中心等产品形态,通过数字化工具,实现门店的用户上平台、交互上平台、交易上平台、交付上平台,从而助力海尔专卖店的零售转型,并实现三翼鸟店的场景创新。
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/57666.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Litctf-web

Litctf-web exx xxe&#xff0c; <?xml version"1.0" encoding"utf-8"?> <!DOCTYPE xxe [<!ELEMENT name ANY ><!ENTITY xxe SYSTEM "file:///flag" >]><user><username>&xxe;</username> …

线程模型介绍

线程模型的介绍 线程有三种模型&#xff1a;N:1用户线程模型&#xff0c;1:1核心线程模式&#xff0c;N:M混合线程模型 POSIX: Portable Operating System Interface(可移值操作系统接口) N&#xff1a;1用户线程模型 线程的实现建立在进程控制的机制之上&#xff0c;有用户…

2024 Rust现代实用教程:1.3获取rust的库国内源以及windows下的操作

文章目录 一、使用Cargo第三方库1.直接修改Cargo.toml2.使用cargo-edit插件3.设置国内源4.与windows下面的rust不同点 参考 一、使用Cargo第三方库 1.直接修改Cargo.toml rust语言的库&#xff1a;crate 黏贴至Cargo.toml 保存完毕之后&#xff0c;自动下载依赖 拷贝crat…

ML 系列:第 18 部 - 高级概率论:条件概率、随机变量和概率分布

文章目录 一、说明二、关于条件概率2.1 为什么我们说条件概率&#xff1f;2.2 为什么条件概率在统计学中很重要 三、 随机变量的定义3.1 定义3.2 条件概率中的随机变量 四、概率分布的定义五、结论 一、说明 条件概率是极其重要的概率概念&#xff0c;它是因果关系的数学表述&…

基于springboot的社区团购系统设计与实现

一、项目背景 网络交易&#xff08;Electronic Commerce&#xff09;&#xff1a;是指实现整个贸易过程中各阶段的贸易活动的电子化。网络交易是一种多技术的集合体。其业务可包括&#xff1a;信息交换、售后服务、销售、电子支付、运输、组建虚拟企业、公司和贸易伙伴可以共同…

挑战Java面试题复习第4天,坚持就是胜利

挑战第 4 天 Excption与Error包结构OOM 知识点SOF 知识点线程程序进程知识点有些字段不想序列化&#xff0c;怎么办&#xff1f;说说 IO 流Java IO与 NIO的区别 Excption与Error包结构 运行时异常&#xff08;RuntimeException&#xff09;&#xff1a; 包括RuntimeException…

一文读懂系列:SSL加密流量检测技术详解

SSL加密流量检测功能的主要目的是为了对加密流量做解密处理&#xff0c;并对解密后的流量做内容安全检查&#xff08;比如反病毒、入侵防御、URL远程查询、内容过滤、文件过滤和邮件过滤等&#xff09;和审计&#xff08;防止信息泄露&#xff09;。接下来我们详细介绍SSL加密流…

dependencyManagement保持maven的多模块依赖版本一致

在maven的多模块中, 为保持jar包在每个子模块中版本一致, 一般会有两种选择&#xff1a; 在父pom的dependencies标签中声明一个jar&#xff0c;每个子模块都会默认继承该jar 如果只有部分子模块用到了一个jar, 则会选择将该jar坐标信息声明在父pom的dependencyManagement标签中…

axis 参数的方向

axis0&#xff1a;表示沿着行的方向进行操作&#xff0c;即对每一列进行操作。 axis1&#xff1a;表示沿着列的方向进行操作&#xff0c;即对每一行进行操作。 示例&#xff1a; import numpy as np# 创建一个二维数组 array np.array([[1, 2, 3],[4, 5, 6],[7, 8, 9] ])axis0…

golang的循环引用解决方法

循环引用是指在数据结构中&#xff0c;两个或多个实体相互引用&#xff0c;形成一个闭环。例如&#xff0c;在 Golang 的结构体中&#xff0c;如果结构体 A 包含结构体 B 的实例&#xff0c;而结构体 B 又包含结构体 A 的实例&#xff0c;这种情况就称为循环引用。以下是关于循…

【C++】关联式容器

1.Set和Map 1.1 set的介绍 set是一个常用的关联式容器&#xff0c;它存储唯一的元素&#xff0c;这些元素默认情况下按照升序排序。其底层是一种自平衡的二叉搜索树(红黑树)。 set元素的键值就是实值&#xff0c;实值就是键值。set的元素允许插入删除但是不允许修改(具有const…

Spring Cloud Function快速入门Demo

1.什么是Spring Cloud Function&#xff1f; Spring Cloud Function是一个具有以下高级目标的项目&#xff1a; 通过功能促进业务逻辑的实现。将业务逻辑的开发生命周期与任何特定的运行时目标脱钩&#xff0c;以便可以将相同的代码作为Web终结点&#xff0c;流处理器或任务来…

第3章 继承与多态

Java面向对象程序设计-T3(继承与多态) 一、封装 1、概述 封装是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。 public class Student {//1、私有化属性private String name;private int age;//2、提供公共方法供外部访问//传入数据public void setName(String nam…

荣誉证书PSD素材(59套免费)

本作品提供荣誉证书PSD素材下载&#xff0c;格式为PSD&#xff1b; 请使用软件Photoshop进行编辑&#xff0c;作品中文字及图均可以通过软件修改和编辑&#xff1b; 点击下载: 荣誉证书PSD素材

Java三大特性之多态

多态是Java的三大特性之一&#xff0c;它指的是同一个方法名字&#xff0c;在不同的对象中有不同的实现方式。具体来说&#xff0c;多态有两种表现形式&#xff1a;静态多态&#xff08;编译时多态&#xff0c;也称为重载&#xff09;和动态多态&#xff08;运行时多态&#xf…

第T6周:Tensorflow实现好莱坞明星识别

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 目标 具体实现 &#xff08;一&#xff09;环境 语言环境&#xff1a;Python 3.10 编 译 器: PyCharm 框 架: &#xff08;二&#xff09;具体步骤 1.查询…

Spring6框架搭建(自用)

一、什么是Spring 众所不周知&#xff0c;Spring就是爪哇人的春天&#xff0c;但是在框架程序设计之前都绕不开javaWeb 1.javaWeb框架发展史 1、ServletJSPJavaBean(跳转页面、业务逻辑判断、数据库查询) 2、MVC三层架构(M Model pojo(User)V-view(USP)C-(controller-servl…

linux-UART

参考博客 https://blog.csdn.net/m0_38106923/article/details/126024970?sharetypeblog&shareId126024970&sharereferAPP&sharesourceweixin_40933496&sharefromlink 1.串口 UART的全称是Universal Asynchronous Receiver and Transmitter&#xff0c;即异步…

大数据治理:策略、技术与挑战

随着信息技术的飞速发展&#xff0c;大数据已经成为现代企业运营和决策的重要基础。然而&#xff0c;大数据的复杂性、多样性和规模性给数据管理带来了前所未有的挑战。因此&#xff0c;大数据治理应运而生&#xff0c;成为确保数据质量、合规性、安全性和可用性的关键手段。本…

vue插件清除 所有console.log()

一、作用 1、提升性能console.log() 语句会消耗一定的性能&#xff0c;尤其是在频繁调用的情况下。在生产环境中移除这些语句可以提高应用的运行效率。 2、减少信息泄露console.log() 可以输出敏感信息&#xff08;如用户数据、API 响应等&#xff09;。在生产环境中&#xf…