Flutter-自适用高度PageView

需求

在 Flutter 中,PageView 是一个非常常用的组件,能够实现多个页面的滑动切换。然而,默认的 PageView 高度是固定的,这在展示不同高度的页面时,可能会导致不必要的空白或内容裁剪问题。为了使 PageView 能够根据每个页面的内容高度动态调整,我们需要一个自适应高度的 PageView 实现。

效果

在这里插入图片描述

本方案的 PageView 可以根据每个页面内容的高度自动调整,保证每个页面的内容在其实际高度内完整显示,并且在页面滑动时,使用平滑的过渡效果。具体来说:

  • 每个页面的内容高度不同,PageView 能够动态调整高度。
  • 页面切换时,高度变化平滑,不会造成突兀的视觉效果。

实现思路

1. 测量每个页面的高度

首先,我们需要为每个页面添加一个高度测量的机制,测量页面内容的高度。在 Flutter 中,我们可以通过 GlobalKeyRenderBox 获取每个 Widget 的实际高度。

2. 动态调整 PageView 高度

在页面滑动时,我们需要根据滑动的进度动态计算当前 PageView 的高度。这就需要在 PageView 的滑动过程中实时更新高度,使得高度随滑动位置逐步过渡。

3. 动态高度过渡

我们可以使用 AnimatedContainer 来平滑过渡 PageView 的高度,避免切换时高度变化过于突兀。通过监听 PageView 的滑动状态,实时调整容器高度。

实现代码

1. 高度测量组件 HeightMeasureWidget

这个组件负责测量每个页面的高度,并将测量结果通过回调传递出去。

import 'package:flutter/material.dart';class HeightMeasureWidget extends StatefulWidget {final Widget child;final Function(double height) onHeightChanged;const HeightMeasureWidget({super.key, required this.child, required this.onHeightChanged});HeightMeasureState createState() => HeightMeasureState();
}class HeightMeasureState extends State<HeightMeasureWidget> {final GlobalKey _key = GlobalKey();void initState() {super.initState();WidgetsBinding.instance.addPostFrameCallback((_) {_measureHeight();});}void _measureHeight() {final RenderBox? renderBox =_key.currentContext!.findRenderObject() as RenderBox?;if (renderBox != null) {widget.onHeightChanged(renderBox.size.height);}}Widget build(BuildContext context) {return Container(key: _key,child: widget.child,);}
}

2. 自适应高度的 AutoHeightPageView

这个组件使用了前面创建的 HeightMeasureWidget 来测量每个页面的高度,然后根据滑动进度调整高度。

import 'package:flutter/material.dart';
import 'measure_height_widget.dart';class AutoHeightPageView extends StatefulWidget {final List<Widget> children;final PageController pageController;const AutoHeightPageView({Key? key,required this.children,required this.pageController,}) : super(key: key);AutoHeightPageViewState createState() => AutoHeightPageViewState();
}class AutoHeightPageViewState extends State<AutoHeightPageView> {final List<double> _heights = [];double _currentHeight = 0;void initState() {super.initState();widget.pageController.addListener(_updateHeight);}void _updateHeight() {if (widget.pageController.position.haveDimensions && _heights.isNotEmpty) {double page = widget.pageController.page ?? 0.0;int index = page.floor();int nextIndex = (index + 1) < _heights.length ? index + 1 : index;double percent = page - index;double height =_heights[index] + (_heights[nextIndex] - _heights[index]) * percent;setState(() {_currentHeight = height;});}}Widget build(BuildContext context) {var isMeasureHeight =_heights.length == widget.children.length ? false : true;return Column(children: [Stack(children: [Visibility(visible: isMeasureHeight,child: Stack(children: widget.children.map((e) => HeightMeasureWidget(child: e,onHeightChanged: (height) {_heights.add(height);if (_heights.length == widget.children.length) {setState(() {_currentHeight = _heights[0];});}},)).toList(),),),if (!isMeasureHeight)AnimatedContainer(duration: const Duration(milliseconds: 200),height: _currentHeight,curve: Curves.easeOut,child: PageView(controller: widget.pageController,children: widget.children,),),],)],);}void dispose() {widget.pageController.dispose();super.dispose();}
}

3. 使用示例 AutoHeightPageViewPage

该页面演示了如何使用自适应高度的 PageView,通过内容高度的动态调整,确保 PageView 始终适应当前页面的高度。

import 'package:flutter/material.dart';
import 'package:flutter_xy/r.dart';
import 'package:flutter_xy/xydemo/vp/pageview/auto_height_page_view.dart';class AutoHeightPageViewPage extends StatefulWidget {const AutoHeightPageViewPage({Key? key}) : super(key: key);State<StatefulWidget> createState() => AutoHeightPageViewState();
}class AutoHeightPageViewState extends State<AutoHeightPageViewPage> {final PageController _pageController = PageController();Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text('自适用高度PageView'),),body: Container(color: Colors.white,child: SingleChildScrollView(child: Column(children: [AutoHeightPageView(pageController: _pageController,children: [Container(color: Colors.white,child: ListView(shrinkWrap: true,physics: const NeverScrollableScrollPhysics(),children: [Container(color: Colors.red,height: 50,alignment: Alignment.center,child: const Text("第一个界面"),),Container(color: Colors.yellow,height: 50,alignment: Alignment.center,child: const Text("第一个界面"),),Container(color: Colors.blue,height: 50,alignment: Alignment.center,child: const Text("第一个界面"),),],),),Container(color: Colors.green,height: 250,child: const Center(child: Text('第二个界面'))),],),Image.asset(R.vp_content_jpg,width: MediaQuery.of(context).size.width,fit: BoxFit.fill,),],),),),);}
}

总结

通过本方案,我们实现了一个自适应高度的 PageView,它能够根据每个页面的内容高度进行动态调整。该实现依赖于对每个页面内容的测量,并使用 AnimatedContainer 来平滑地过渡高度变化。这样可以确保页面切换时,用户体验更加自然流畅,避免了内容被裁剪或空白区域的出现。这种自适应高度的 PageView 非常适合用于不同页面内容高度不一致的场景。

详情:github.com/yixiaolunhui/flutter_xy

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

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

相关文章

OpenMax算法详解:深度学习中的高效开集识别技术

OpenMax算法详解&#xff1a;深度学习中的高效开集识别技术 在深度学习领域&#xff0c;模型的识别能力往往受限于其训练数据集的范畴。传统的分类模型&#xff0c;如卷积神经网络&#xff08;CNN&#xff09;或循环神经网络&#xff08;RNN&#xff09;&#xff0c;通常被设计…

第八节:Nodify 编辑器属性

引言 经过前几章的学习&#xff0c;你已经对Nodify框架有了初步的编程思路。当然只局限于这些还完全不够&#xff0c;本章节将阐述各个结构组件的一些常用属性&#xff0c;以便在日后的开发过程中更得心应手。 1、编辑器 平移 简介属性默认值平移功能 控制DisablePanningfals…

100128-批量获取视频音频时长添加到文件名中支持子孙文件夹下操作-UI

程序功使用环境▶适用的系统环境说明&#xff1a;win7以上64位win系统注意&#xff1a;win32位系统/mac系统需要额外定制▶使用期限&#xff1a;无需注册、不绑电脑、无时间限制▶如何安装&#xff1a;不需要安装程序功能说明▶子文件夹穿透&#xff1a;支持▶支持的文件格式&a…

MySQL集群技术详解

目录 一、MySQL在服务器中的部署方法 1.1 编译安装MySQL 1.2 部署MySQL 二、MySQL主从复制 2.1 配置master 2.2 配置slave 2.3 添加slave2 测试&#xff1a; 2.4 延迟复制 2.5 慢查询日志 2.6 MySQL的并行复制 2.7 MySQL主从复制原理剖析 2.8 架构缺陷 三、MySQL…

学习笔记——IP组播——IP组播基本概述

二、IP组播基本概述 IP组播技术有效地解决了单播和广播在点到多点应用中的问题。组播源只发送一份数据&#xff0c;数据在网络节点间被复制、分发&#xff08;PIM&#xff09;&#xff0c;且只发送给需要该信息的接收者。 1、前言 网络中存在各种各样的业务&#xff0c;从流…

EasyCVR视频汇聚平台革新播放体验:WebRTC协议赋能H.265视频流畅传输

随着科技的飞速发展和网络技术的不断革新&#xff0c;视频监控已经广泛应用于社会各个领域&#xff0c;成为现代安全管理的重要组成部分。在视频监控领域&#xff0c;视频编码技术的选择尤为重要&#xff0c;它不仅关系到视频的质量&#xff0c;还直接影响到视频的传输效率和兼…

企业参与制定行业标准的主要途径有哪些?需要具备哪些条件?

在当今竞争激烈的商业环境中&#xff0c;参与制定行业标准已成为企业提升竞争力、塑造行业地位的重要战略举措。然而&#xff0c;并非所有企业都有能力和资格参与这一重要的活动。要想在行业标准制定的舞台上发挥积极作用&#xff0c;企业需要具备一系列关键条件。 企业参与制…

mapstruct和lombok同时使用时,转换实体类时数据丢失

全局搜一下maps&#xff0c;找到你进行转换的方法 可以看到新建了TswCaseInfoPlus后直接返回了&#xff0c;说明TswCaseInfoPlus没有set方法&#xff0c;或者说编译后lombok没生效 在pom文件中&#xff0c;编译打包插件中将lombok&#xff0c;mapstruct&#xff0c;lombok-map…

3ds Max - 导出顶点色模型

很久之前的笔记&#xff0c;整理归档&#xff1b; 在3ds Max中&#xff0c;给模型添加VetexPaint修改器后&#xff0c;可以给模型&#xff08;顶点色通道R\G\B默认值为255\255\255&#xff09;刷不同颜色的顶点色&#xff08;默认为黑色&#xff0c;即让RGB通道都为0&#xff0…

PY信号和槽

知不足而奋进 望远山而前行 提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 系列文章目录前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 前言 在使用PyQt进行图形用户界面&#xff08;GU…

jenkins发送html邮件配置步骤与注意事项?

jenkins发送html邮件如何实现&#xff1f;Jenkins的配置方法&#xff1f; 通过jenkins发送html邮件&#xff0c;开发团队可以及时获取构建状态的详细报告&#xff0c;从而快速响应问题&#xff0c;提高工作效率。AokSend将详细介绍jenkins发送html邮件的配置步骤与注意事项&am…

【实现100个unity特效之28】皮毛shader着色器 实现可以用动的毛茸茸毛绒绒效果

效果 文章目录 效果一、内置渲染管线下载支持几只着色器Basic 基本Attributes 属性Force 力Rim Color 轮辋颜色 二、URP下载几只毛发着色器实现的示例Shell 壳Fin 翅片Fur Polygon 毛发多边形Compare 比较Move 移动 完结 一、内置渲染管线 缺点是仅支持内置渲染管线。且无法毛…

各个版本jdk新特性

jdk8新特性 方法引用&#xff1a;方法引用允许直接通过方法的名称来引用已经存在的方法&#xff0c;简化了函数式接口的实现。默认方法&#xff08;Default Methods&#xff09;&#xff1a;默认方法允许在接口中定义具有默认实现的方法&#xff0c;以便接口的实现类可以继承该…

Linux基础知识(一、什么是Linux)

一、Linux之父——林纳斯本纳第克特托瓦兹&#xff08;Linus Benedict Torvalds&#xff09; Linux操作系统最初是在1991年10月份由芬兰赫尔辛基大学的在校生Linus Torvalds所发布,最初被发布的LINUX0.02版本因其高质量的代码与开放源代码&#xff0c;迅速引起了一大批黑客的加…

STL中的stack与queue

前言&#xff1a; stack与queue是STL中的容器适配器&#xff0c;而不是容器。何为适配器&#xff1f;给手机充电的充电器就是一种适配器&#xff0c;将高电压变成低电压。适配器是用来做转化的&#xff0c;不用来直接管理数据&#xff0c;而是在其他容器的基础上去封装转换。 …

【Cadence23】Cadence HDL原理图如何将两个不同的全局网络连接

【转载】Cadence Design Entry HDL 使用教程 【Cadence01】Cadence PCB Edit相对延迟与绝对延迟的显示问题 【Cadence02】Allegro引脚焊盘Pin设置为透明 【Cadence03】cadence不小心删掉钢网层怎么办&#xff1f; 【Cadence04】一般情况下Allegro PCB设计时的约束规则设置&a…

Linux驱动开发基础(中断)

所学来自百问网 目录 1. 嵌入式中断系统 2. 中断处理流程 3. 异常向量表 4. Linux系统对中断的处理 4.1 ARM 处理器程序运行的过程 4.2 保护现场 5. Linux 系统对中断处理的演进 5.1 硬件中断和软件中断 5.2 中断拆分(上半部和下半部) 5.2.1 tasklet 5.2.2 工作队列…

Autofac容器

IoC&#xff1a;注册、注入&#xff08;解析&#xff09;、生命周期 Autofac的基本使用 基本使用 需要在NuGet包安装Autofac---建议7.1.0版本 注册&#xff1a; 默认注册&#xff1a; // 容器的初始化 ContainerBuilder builder new ContainerBuilder(); // 注册需要解析…

K8S部署MySQL5.7的主从服务

mysql-slave-0是master mysql-slave-1是slave 当mysql写的时候&#xff0c;找headless service中的 mysql-slave-0.mysql57-slave-headless&#xff1b;当mysql读的时候&#xff0c;找clusterip service中的mysql57-slave-read读&#xff0c;实现读写分离。 statefulset维护两个…

Linux操作系统常见面试题

前言 作者&#xff1a;小蜗牛向前冲 名言&#xff1a;我可以接受失败&#xff0c;但我不能接受放弃 如果觉的博主的文章还不错的话&#xff0c;还请点赞&#xff0c;收藏&#xff0c;关注&#x1f440;支持博主。如果发现有问题的地方欢迎❀大家在评论区指正 分享常见的操作系统…