ScrollView 与 SliverPadding 的关系

news2024/10/7 16:22:40

基本页面布局

Scaffold 中有个 ListView,ListView 中有 100 个高 50 的 Container 用作辅助观看,ListView 中第三个元素是一个 GridView,GridView 的滑动效果被禁止。

class GiveView extends GetView<GiveController> {
  const GiveView({Key? key}) : super(key: key);
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('GiveView'),
        centerTitle: true,
      ),
      body: ListView.builder(
        itemCount: 100,
        itemBuilder: (context, index) {
          if (index == 3) {
            return SizedBox(
              height: 220,
              child: GridView.builder(
                itemCount: 10,
                gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
                  crossAxisCount: 5,
                  mainAxisExtent: 100,
                  crossAxisSpacing: 20,
                  mainAxisSpacing: 20,
                ),
                itemBuilder: (BuildContext context, int index) {
                  return Image.network(
                      'https://img.xjh.me/random_img.php?return=302&time=${DateTime.now().microsecond}');
                },
              ),
            );
          }
          return Container(
            margin: const EdgeInsets.symmetric(vertical: 5),
            height: 50,
            decoration: BoxDecoration(
              border: Border.all(),
              color: Colors.amber,
            ),
          );
        },
      ),
    );
  }
}

如上图所示,要探究的问题就以此为基础。

与 AppBar 的关系

目前为止,页面布局看着都很正常,没有问题。

去掉 AppBar

有时候是不需要 AppBar 的,比如:

去掉之后变成了如下摸样,明显不符合预期,上边的状态栏、刘海都空白了,没有完全占满。就好像 ListView 与最上边有了一个状态栏高度的距离,至于是 Margin,还是 Padding,又或者是一个空的 Container,继续向下查看。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

通过查看 ListView 源码发现,在 packages/flutter/lib/src/widgets/scroll_view.dart:807 处发现会获取当前上下文的 mediaQuery 对象,并使用其中的 Padding。

ScrollView(ListView、GridView、BoxScrollView 的抽象类),在 build 时,会调用 buildSlivers,先看自身有没有设置 padding,如果设置了,那就用自己的。没设置就看 Widget 树中,最近的一个 MediaQuery 它的 padding 信息,以其为主。

找到了对应的代码逻辑,可以通过 Debug 和 DevTools 进行确认一下。

Debug 查看:

DevTools 查看:

由此也能看出,离 ListView 最近的一个 MediaQuery,其 Padding top 是 59,也就是状态栏的高度。

加上 AppBar

上面看到了去掉 AppBar 的情况,为了相互印证,把 AppBar 再加上进行查看。

Debug 查看:

DevTools 查看:

解决去掉 AppBar 的问题

方案 1

通过刚才的分析,现在已经很明白了,只需要给自己的 ScrollView 设置上 padding 即可,他就不会进入下面的代码:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

最终代码:

效果:

完美,咦,不对,怎么中间的 GridView 的布局不对劲了?看着应该是离上边有个状态栏高度的 padding,真是“拆了东墙补西墙”。细细想想,把 ListView 的 padding 设置上了,它用自己的 padding 了,可是 GridView 也是 ScrollView 的实现,所以它也会走这块代码:

方案 2

GridView 可没有给他设置 padding,所以它还是用 Scaffold 下、GridView 上(Widget 树中)的那个 MediaQuery 中的 padding 信息,所以还是有个 top: 59 的距离,简单做法就是给 GridView 也设置上他自己的 padding,可是我已经烦了,难道每多一个 ScrollView 就要给他设置个 padding?

既然知道是 ScrollView 最近的 MediaQuery 导致的,那可以不可以一劳永逸,把这个最近的 MediaQuery 换了?当然可以,这里在 ListView 外边加一个自己的 MediaQuery:

Widget build(BuildContext context) {
  return Scaffold(
    // 手动增加一层 MediaQuery,默认的 padding 为 0
    body: MediaQuery(
      data: const MediaQueryData(),
      child: ListView.builder(
        itemCount: 100,
        itemBuilder: (context, index) {
          if (index == 3) {
            return SizedBox(
              height: 220,
              child: GridView.builder(
                physics: const NeverScrollableScrollPhysics(),
                itemCount: 10,
                gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
                  crossAxisCount: 5,
                  mainAxisExtent: 100,
                  crossAxisSpacing: 20,
                  mainAxisSpacing: 20,
                ),
                itemBuilder: (BuildContext context, int index) {
                  return Image.network(
                      'https://img.xjh.me/random_img.php?return=302&time=${DateTime.now().microsecond}');
                },
              ),
            );
          }
          return Container(
            margin: const EdgeInsets.symmetric(vertical: 5),
            height: 50,
            decoration: BoxDecoration(
              border: Border.all(),
              color: Colors.amber,
            ),
          );
        },
      ),
    ),
  );
}

这样在 Scaffold 下、ListView 上就是自己创建的这个 MediaQuery 了。

还有另一种方式是使用 MediaQuery.removePadding 是一样的道理。

外部 ScrollView 使用 padding 与不使用的区别

恢复到自己插入 MediaQuery 之前的代码:

Widget build(BuildContext context) {
  return Scaffold(
    body: ListView.builder(
      itemCount: 100,
      itemBuilder: (context, index) {
        if (index == 3) {
          return SizedBox(
            height: 220,
            child: GridView.builder(
              physics: const NeverScrollableScrollPhysics(),
              itemCount: 10,
              gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
                crossAxisCount: 5,
                mainAxisExtent: 100,
                crossAxisSpacing: 20,
                mainAxisSpacing: 20,
              ),
              itemBuilder: (BuildContext context, int index) {
                return Image.network(
                    'https://img.xjh.me/random_img.php?return=302&time=${DateTime.now().microsecond}');
              },
            ),
          );
        }
        return Container(
          margin: const EdgeInsets.symmetric(vertical: 5),
          height: 50,
          decoration: BoxDecoration(
            border: Border.all(),
            color: Colors.amber,
          ),
        );
      },
    ),
  );
}

给 ListView 加上 padding:

这两个的区别就在于 ListView 加不加 padding。

  • 没加:内部的 ScrollView 布局正常。
  • 加了:内部的 ScrollView 布局异常,有一个高度为状态栏高度的 top padding。

那来分析分析原因,还得回到 ScrollView 的 buildSlivers 中(packages/flutter/lib/src/widgets/scroll_view.dart:803)。

前者

先说前者,ListView 没有设置 padding,所以会执行红框范围的代码,其中 819 行包裹了一层 MediaQuery,这就和上边自行加一层 MediaQuery 的效果是一样的了,后续在 ListView 中的 ScrollView 都将默认使用此 MediaQuery,所以布局没有问题。

后者

后者,由于 ListView 设置有 padding,就不会走红框范围的代码,那也就不会在 Widget 树中增加一个 MediaQuery,所以在 ListView 内部的 ScrollView 如果自己不设置 padding,还是会使用那个 padding top = 59 的 MediaQuery。

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

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

相关文章

振南技术干货集:研发版本乱到“妈不认”? Git!(2)

注解目录 1、关于 Git 1.1Git 今生 (Git 和 Linux 的生父都是 Linus&#xff0c;振南给你讲讲当初关于 Git 的爱恨情愁&#xff0c;其背后其实是开源与闭源两左阵营的明争暗斗。) 1.2Git的爆发 (Git 超越时代的分布式思想。振南再给你讲讲旧金山三个年轻人创办 GitHub&…

开源绘画krita中的笔刷压感开启技巧

一、问题描述 之前用过高漫的绘图板&#xff0c;在krita中没有效果&#xff0c; 原来是因为压感没有开启。方法如下。 二、解决方法 如下图点击笔刷设置按钮&#xff0c;打开 笔刷编辑器&#xff0c;之后如图顺序&#xff0c;从左栏点击笔刷控制属性“大小”&#xff0c;之…

【MySQL基本功系列】第二篇 InnoDB存储引擎的架构设计

通过上一篇文章&#xff0c;我们简要了解了MySQL的运行逻辑&#xff0c;从用户请求到最终将数据写入磁盘的整个过程。当数据写入磁盘时&#xff0c;存储引擎扮演着关键的角色&#xff0c;它负责实际的数据存储和检索。在MySQL中&#xff0c;有多个存储引擎可供选择&#xff0c;…

51单片机PCF8591数字电压表LCD1602液晶显示设计( proteus仿真+程序+设计报告+讲解视频)

51单片机PCF8591数字电压表LCD1602液晶设计 ( proteus仿真程序设计报告讲解视频&#xff09; 仿真图proteus7.8及以上 程序编译器&#xff1a;keil 4/keil 5 编程语言&#xff1a;C语言 设计编号&#xff1a;S0060 51单片机PCF8591数字电压表LCD1602液晶设计 1.主要功能&a…

Python高级语法----Python装饰器的艺术

文章目录 装饰器基础示例代码:执行结果:参数化装饰器示例代码:执行结果:类装饰器示例代码:执行结果:装饰器的堆栈示例代码:执行结果:在Python中,装饰器是一种非常强大的特性,允许开发人员以一种干净、可读性强的方式修改或增强函数和方法。以下是一个关于Python装饰器…

如何使用安卓手机数据恢复软件从安卓手机恢复数据

在 Android 上丢失数据并不是世界末日。拿起您的设备&#xff0c;利用最好的 Android 数据恢复软件来恢复手机内存或 SD 卡中的文件、通话记录、消息、联系人、照片、视频等。 在使用 Android 手机的过程中&#xff0c;您会体会到数字存储的便利性&#xff0c;它可以保存大量数…

elemenui的Upload上传整合成数组对象

1. 普通直接上传 <el-upload action"" :before-upload"doBeforeUpload"><el-button type"success" size"mini">导入</el-button></el-upload> methods:{doBeforeUpload(file) {let reader new FileReader(…

简单得令人尴尬的FSQ:“四舍五入”超越了VQ-VAE

©PaperWeekly 原创 作者 | 苏剑林 单位 | 月之暗面 研究方向 | NLP、神经网络 正如 “XXX is all you need” 一样&#xff0c;有不少论文都以“简单得令人尴尬”命名&#xff08;An Embarrassingly Simple XXX&#xff09;&#xff0c;但在笔者看来&#xff0c;这些论文…

8种很坑的SQL错误用法

1、LIMIT 语句 分页查询是最常见的场景之一&#xff0c;但也通常也是最容易出问题的地方。例如对于下面简单的语句&#xff0c;一般 DBA 想到的办法是在 type, name, create_time 字段上加组合索引。这样条件排序都能有效的利用到索引&#xff0c;性能迅速提升。 好吧&#xf…

docker 拉取镜像

2.2.1、拉取镜像java:8(jdk1.8) docker pull java:8 2.2.2、拉取镜像mysql:8.2.0 docker pull mysql:8.2.0 2.2.3、拉取镜像redis:7.0.14 docker pull redis:7.0.14 2.2.4、拉取镜像nginx:1.25.3 docker pull nginx:1.25.3 2.2.5、查看镜像 docker images 启动镜像 …

Vatee万腾的科技决策力奇迹:Vatee科技决策力的独特之选

在金融投资的复杂领域中&#xff0c;Vatee万腾以其独特的科技决策力创造了一场真正的奇迹。这不仅是一种引领投资者走向成功的选择&#xff0c;更是一种开启新时代的科技决策奇迹。 Vatee的科技决策力背后蕴藏着强大的智慧和创新。通过大数据分析、智能算法的运用&#xff0c;V…

华为防火墙二层透明模式下双机热备主备备份配置(两端为交换机)

这种模式只能是主备备份模式&#xff0c;不能是负载分担&#xff0c;因为会有环路。 故障切换是&#xff0c;如果主故障&#xff0c;主设备所有接口全都会down状态&#xff0c;然后再up一次&#xff0c;用于改变mac转发表。 FW1 hrp enable hrp interface GigabitEthernet1/0…

【赠书活动】嵌入式虚拟化技术与应用

文章目录 前言 1 背景概述 2 专家推荐 3 本书适合谁&#xff1f; 4 内容简介 5 书籍目录 6 权威作者团队 7 粉丝福利 前言 随着物联网设备急剧增长和万物互联应用迅速发展&#xff0c;虚拟化技术成为嵌入式系统焦点。这反映了信息技术迫切需求更高效、灵活和可靠系统。…

Excel 常用技巧

1: 拼接 公式: C1&B1&A1 如 D CBA 将公式输入目标列之后回车即可得到结果 , 如果有多行需要处理 , 光标选中目标单元格右下角变为 按着左键下拉即可 最后选择转换功能转换为文本即可 2: 时间戳转时间格式 公式: TEXT((B2/10008*3600)/8640070*36519,"yyyy/mm…

100V耐压内置MOS ESOP8 40V输入转5V 2.1A恒压输出

100V耐压内置MOS ESOP8 40V输入转5V 2.1A恒压输出 SC9102 是一款宽电压范围降压型 DC-DC 电源管理芯片&#xff0c;内部集成使能开关控制、基准电源、误差放大器、 过热保护、限流保护、短路保护等功能&#xff0c;非常适合宽电压输入降压使用。 SC9102 零功耗使能控制&…

Transmit :macOS 好用的 Ftp/SFtp 工具

Transmit 是一种功能强大的 FTP/SFTP/WebDAV 客户端软件&#xff0c;是一个 Mac OS X 平台上设计的文件传输软件。它由 Panic&#xff08;一家以软件工具为主的公司&#xff09;开发和维护&#xff0c;是一款非常受欢迎且易于使用的软件&#xff0c;而且被广泛认为是 Mac OS X …

【C++】哈希 Hash(闭散列、开散列介绍及其实现)

一、unordered系列关联式容器 在 C98 中&#xff0c;STL 提供了底层为红黑树结构的一系列关联式容器&#xff0c;在查询时效率可达到 O(logN)&#xff0c;即最差情况下需要比较红黑树的高度次&#xff0c;当树中的节点非常多时&#xff0c;查询效率也不理想。最好的查询是&…

ChatGPT显现“ Something went wrong. If this issue persists ...”什么原因?如何解决?

一、报错提示 Something went wrong. If this issue persists please contact us through our help center at help.openai.com. 二、解决方案 一般是代理节点出现问题 ChatGPT退出登录 关闭代理并重新启动代理 切换其他节点 清除浏览器缓存 重新登录ChatGPT 三、其它思路…

模电学习路径--google镜像chatgpt

交流通路实质 列出电路方程1&#xff0c;方程1对时刻t做微分 所得方程1‘ 即为 交流通路 方程1对时刻t做微分&#xff1a;两个不同时刻的方程1相减&#xff0c;并 令两时刻差为 无穷小 微分 改成 差 模电学习路径&#xff1a; 理论 《电路原理》清华大学 于歆杰 朱桂萍 陆文…

使用大型语言模型进行文本摘要

路易斯费尔南多托雷斯 &#x1f4dd; Text Summarization with Large Language Models。通过单击链接&#xff0c;您将能够逐步阅读完整的过程&#xff0c;并与图进行交互。谢谢你&#xff01; 一、介绍 2022 年 11 月 30 日&#xff0c;标志着机器学习历史上的重要篇章。就在这…