Flutter-自适用高度PageView

news/2024/9/18 14:52:32/ 标签: flutter, javascript, 开发语言

需求

在 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.ppmy.cn/news/1516494.html

相关文章

云计算环境下的等保测评要点分析

在云计算环境下进行等保测评时&#xff0c;需要关注以下几个关键点&#xff1a; 安全责任共担模型&#xff1a;明确云服务提供商&#xff08;CSP&#xff09;与云服务用户&#xff08;CSU&#xff09;之间的安全责任划分&#xff0c;确保双方在安全防护上的协同作用。 安全控制…

【笛卡尔积】深入理解笛卡尔积及其在SQL中的应用

文章目录 引言笛卡尔积的定义数学背景SQL 中的笛卡尔积 SQL 示例基础示例复杂示例使用 WHERE子句限制结果集 笛卡尔积的实际应用笛卡尔积的性能考虑性能影响 更多相关内容可查看 在一个阳光明媚的周一清晨&#xff0c;听到这个词汇突然觉得有点陌生才有了此文的诞生 引言 在数…

33. 二叉搜索树的后序遍历序列【难】

comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/lcof/%E9%9D%A2%E8%AF%95%E9%A2%9833.%20%E4%BA%8C%E5%8F%89%E6%90%9C%E7%B4%A2%E6%A0%91%E7%9A%84%E5%90%8E%E5%BA%8F%E9%81%8D%E5%8E%86%E5%BA%8F%E5%88%97/README.md 面试题 33. 二…

破晓科技与神话:三防平板与《黑神话:悟空》的创新交响

当全球游戏圈因《黑神话&#xff1a;悟空》的震撼预告而沸腾&#xff0c;一款代表中国游戏顶尖制作水平的作品&#xff0c;正以它独特的文化魅力与技术创新&#xff0c;向世界宣告着中国游戏产业的崛起。 点击添加图片描述&#xff08;最多60个字&#xff09;编辑 震撼视觉体验…

nginx正向代理与反向代理功能

Nginx是一款高性能的HTTP和反向代理服务器&#xff0c;同时也是一个IMAP/POP3/SMTP代理服务器。它的正向代理和反向代理功能在实际工作中有广泛的应用。 正向代理 功能 正向代理是位于客户端和原始服务器之间的代理服务器。客户端&#xff08;例如浏览器&#xff09;向代理服…

记录一个iOS工程添加文件的问题

遇到一个紧急问题&#xff0c;将工程copy了一份&#xff0c;然后需要将copy工程的一个文件夹 拖到现有的工程里面&#xff0c;由于事情紧急&#xff0c;就直接从工程目录中拖拽文件夹&#xff0c; 如下图 拖过之后&#xff0c;本地项目能跑了&#xff0c;但是远端自动化构建是…

排序算法之选择排序详细解读(附带Java代码解读)

选择排序&#xff08;Selection Sort&#xff09;是一种简单且直观的排序算法。它的基本思想是&#xff1a;每一轮从未排序的部分中选出最小&#xff08;或最大&#xff09;的元素&#xff0c;放到已排序部分的末尾。通过不断地选择最小&#xff08;或最大&#xff09;元素&…

MybatisPlus:实现分页效果并解决错误:cant found IPage for args

我们在做开发使用mybatisplus 做分页查询的时候遇到了个问题&#xff1a; 继承 IPage拦截没有作用会默认分页&#xff0c;这个时候报了cant found IPage for args 错误~~~ 我们分析了下&#xff0c;其实这个问题很简单&#xff0c;是因为没有给默认值赋值&#xff0c;因为查询…

申报合肥市各区县高新技术企业认定奖励补助政策

&#xff08;一&#xff09;合肥市 对首次认定为国家高新技术企业给予10万元奖励&#xff0c;并落实国家各项税收优惠支持政策。对符合条件的入库国家科技型中小企业&#xff0c;按符合加计扣除条件的研发费用10%&#xff0c;给予10万元—50万元补贴。 &#xff08;政策来源&…

鸿蒙高级开发者认证题库(2)

20.项目需要为不同的设备形态(如手机、智能手表)提供定制化构建。请说明如何在DevEco studio中设置不同的构建配置&#xff0c;以生成针对不同设备的hap包? A.在工程级别build-profile.ison5定义多个 product&#xff0c;在每个product的config/deviceType中定义不同的设备类…

攻防世界 1000次点击

做题笔记。 下载解压 查壳。 32位ida打开。 查找字符串。 winmain函数写的&#xff0c;程序运行如下&#xff1a; 一开始思路是想着分析找到关键代码然后去od进行调试。 后来&#xff0c;额&#xff0c;不想看代码了。吐了。 尝试去字符串搜索flag样式&#xff0c;确实一发现…

数据结构(6_3_1)——图的广度优先遍历

树和图的广度优先遍历区别 树的广度优先遍历&#xff1a; 图的广度优先遍历&#xff1a; 代码&#xff1a; 注:以下代码只适合连通图 #include <stdio.h> #include <stdbool.h>#define MAX_VERTEX_NUM 100typedef struct ArcNode {int adjvex; // 该边所指向的顶…

链表(含代码)

好久没更新了&#xff0c;今天浅浅更新一下。 今天给大家主要分享一下链表的一些知识。 链表的首先方式主要有两种&#xff0c;一种是结构体加指针&#xff0c;另一种是拿数组模拟链表。 一、结构体加指针&#xff08;每次都要调用new Node&#xff08;&#xff09;函数&…

优化|计算合作博弈的成本分摊

原文&#xff1a; Caprara, A., & Letchford, A. N. (2010). New techniques for cost sharing in combinatorial optimization games. Mathematical programming, 124, 93-118. https://doi.org/10.1007/s10107-010-0357-7. 原文作者&#xff1a; Alberto Caprara, Adam N…

【功能实现】axios实现动态数据

1.安装axios npm i axios 2.axios调取数据 import { onMounted,ref } from "vue"const titleListref([])//获取数据库数据&#xff0c;将数据赋值给titleListconst getArticles async () > {const result await axios.get(http://127.0.0.1:3000/getAccount)t…

嵌入式Linux学习笔记

1.文件操作命令 2.VI编辑器的部分命令 3.Uboot命令设置环境变量 4. uboot 的顶层 Makefile的重点是“make xxx_defconfig”和“make”这两个命令 &#xff0c;分别如下&#xff1a; 5.在串口SecureCRT中利用uboot启动Linux内核的两种方式 6.Linux内核移植到开发板上也可以反…

C#/.NET/.NET Core技术前沿周刊 | 第 2 期(2024年8.19-8.25)

前言 C#/.NET/.NET Core技术前沿周刊&#xff0c;你的每周技术指南针&#xff01;记录、追踪C#/.NET/.NET Core领域、生态的每周最新、最实用、最有价值的技术文章、社区动态、优质项目和学习资源等。让你时刻站在技术前沿&#xff0c;助力技术成长与视野拓宽。 欢迎投稿&…

MFC之word操作

MFC对word操作 背景说明 当对程序的内容进行输出时&#xff0c;比如自定义对象属性描述或者注释&#xff08;详细设计&#xff09;生成文档时&#xff0c;如果采用手动输入会比较麻烦&#xff0c;并且当程序变动时&#xff0c;需要再一次修改对应文档&#xff0c;作为程序员做…

修复 502 Bad Gateway 错误的 6 种方法

通常&#xff0c;我们在使用网站时可能会遇到一系列错误。有些非常常见&#xff0c;例如 404&#xff0c;有些则不太常见&#xff0c;例如 101。这些被称为 HTTP 状态代码。其中&#xff0c;502 错误是某种服务器错误。那么&#xff0c;让我们先了解一下 Bad Gateway 502 的含义…

EazyDraw for Mac 矢量图绘制设计软件

Mac分享吧 文章目录 效果一、下载软件二、开始安装1、双击运行软件&#xff0c;将其从左侧拖入右侧文件夹中&#xff0c;等待安装完毕2、应用程序显示软件图标&#xff0c;表示安装成功 三、运行测试安装完成&#xff01;&#xff01;&#xff01; 效果 一、下载软件 下载软件…