当前位置: 首页 > news >正文

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

相关文章:

Flutter-自适用高度PageView

需求 在 Flutter 中&#xff0c;PageView 是一个非常常用的组件&#xff0c;能够实现多个页面的滑动切换。然而&#xff0c;默认的 PageView 高度是固定的&#xff0c;这在展示不同高度的页面时&#xff0c;可能会导致不必要的空白或内容裁剪问题。为了使 PageView 能够根据每…...

群晖NAS本地搭建可远程交互的大型语言模型LLM聊天机器人

文章目录 前言1. 拉取相关的Docker镜像2. 运行Ollama 镜像3. 运行Chatbot Ollama镜像4. 本地访问5. 群晖安装Cpolar6. 配置公网地址7. 公网访问8. 固定公网地址 前言 本文主要分享如何在群晖NAS本地部署并运行一个基于大语言模型Llama 2的个人本地聊天机器人并结合内网穿透工具…...

TypeScript 构建工具之 webpack

在实际开发中&#xff0c;直接使用TypeScript 编译器的情况不多。 在项目中&#xff0c;需要使用构建工具对代码进行打包&#xff0c;不可能脱离项目使用TypeScript 编译器单独打包TypeScript 。 那如何将 webpack 和 TypeScript 进行集成&#xff1f; 参考文档&#xff1a; w…...

conda环境下在pycharm中调试scrapy项目

前提条件 已经创建好了conda环境已经安装好了scrapy框架项目初始化完成 编写一个爬虫脚本 import scrapyclass StackOverflowSpider(scrapy.Spider):name stackoverflowstart_urls [http://stackoverflow.com/questions?sortvotes]def parse(self, response):print("…...

contenteditable=“true“的标签限制字数的时候修改光标位置

contenteditable"true"的标签限制字数的时候修改光标位置 有时候input和textarea并不能完全满足ui需求&#xff0c;这个时候我们就用contenteditable"true"来将别的标签修改为可编辑状态&#xff0c;但当我们通过js修改了内容之后光标的位置就是一个问题&…...

51单片机-LED灯蜂鸣器数码管按键DS18B20温度传感器

LDE灯的相关程序 LED灯闪烁 LED流水灯 方法1 方法二&#xff1a; 因为P1口可以直接控制P1^0~P1^7的8个led灯&#xff0c;利用一个8位的二进制数字来进行控制即可。如果要点亮P1^0 只需要给P1口传递 1111 1110即可。 蜂鸣器的使用 什么是蜂鸣器&#xff1f; 蜂鸣器是一种一…...

笔记本一线品牌有哪些

笔记本电脑的一线品牌通常指的是在市场上具有较高市场份额、良好口碑、较强的技术实力和服务能力的品牌。根据目前的信息&#xff0c;笔记本电脑市场的一线品牌主要包括以下几个&#xff1a; 联想 (Lenovo)&#xff1a;联想在全球笔记本市场上的占有率较高&#xff0c;其产品线…...

mysql聚合函数和分组

我最近开了几个专栏&#xff0c;诚信互三&#xff01; > |||《算法专栏》&#xff1a;&#xff1a;刷题教程来自网站《代码随想录》。||| > |||《C专栏》&#xff1a;&#xff1a;记录我学习C的经历&#xff0c;看完你一定会有收获。||| > |||《Linux专栏》&#xff1…...

ubuntu20.04+RealSenseD455

ubuntu20.04安装驱动双目相机RealSenseD455 安装环境安装RealSense SDK 2.0ROS包安装启动Realsense摄像头存在的 bugD455标定安装环境 系统:Ubuntu20.04 ROS:Noetic 视觉传感器:Intel RealSense D455 安装RealSense SDK 2.0 该安装有两种方式,一个是用命令安装,另一个是…...

WAF绕过技巧

WAF绕过技巧 WAF&#xff08;Web Application Firewall&#xff09;是一种安全系统&#xff0c;旨在监控和控制网络流量&#xff0c;以防止攻击&#xff0c;如SQL 注入、跨站脚本&#xff08;XSS&#xff09;和拒绝服务&#xff08;DoS&#xff09;。 WAF 可以通过多种方式绕过…...

HarmonyOS应用三之组件生命周期和参数传递

目录&#xff1a; 1、生命周期的执行顺序2、页面数据传递3、图片的读取4、数据的备份和恢复5、轮播图6、页面布局图 1、生命周期的执行顺序 /** Copyright (c) 2023 Huawei Device Co., Ltd.* Licensed under the Apache License, Version 2.0 (the "License");* yo…...

[Qt][Qt 网络][上]详细讲解

目录 0.概述1.UDP Socket1.核心API概览2.回显服务器3.回显客户端 0.概述 要使用Qt中有关网络编程的API&#xff0c;需要添加network模块 1.UDP Socket 1.核心API概览 主要的类有两个&#xff1a;QUdpSocket和QNetworkDatagramQUdpSocket表⽰⼀个UDP的socket⽂件 bind(const …...

读零信任网络:在不可信网络中构建安全系统21读后总结与感想兼导读

1. 基本信息 零信任网络&#xff1a;在不可信网络中构建安全系统 道格巴斯&#xff08;Doug Barth&#xff09; 著 人民邮电出版社,2019年8月出版 1.1. 读薄率 书籍总字数252千字&#xff0c;笔记总字数73194字。 读薄率73194252000≈29.5% 这个读薄率是最高的吧&#x…...

Java基础——注释

在开发中注释是必不可少的&#xff0c;帮助我们更好的标记阅读代码&#xff0c;下面介绍几种常用的注释方式。 一、注释种类 1. 单行注释 使用//一行代码来进行注释&#xff0c;只能注释一行内容 2. 多行注释 使用斜杠星号的方式 /*注释多行代码*/&#xff0c;注释多行代…...

Redis未授权访问漏洞利用合集

一、基本信息 靶机&#xff1a;IP:192.168.100.40 攻击机&#xff1a;IP:192.168.100.60 二、漏洞 & 过程 Redis 未授权访问漏洞利用无口令远程登录靶机 靶机 cd redis-4.0.8/src./redis-server ../redis.conf 攻击机 ./redis-cli -h 192.168.100.40 Redis 未授权访问…...

基于asp.net的在线考试系统、基于c#的在线考试管理系统

摘 要 伴随着社会以及科学技术的发展&#xff0c;互联网已经渗透在人们的身边&#xff0c;网络慢慢的变成了人们的生活必不可少的一部分&#xff0c;紧接着网络飞速的发展&#xff0c;管理系统这一名词已不陌生&#xff0c;越来越多的学校、公司等机构都会定制一款属于自己个…...

将 hugo 博客搬迁到服务器

1. 说明 在 Ubuntu 22.04 上使用 root 账号&#xff0c;创建普通账号&#xff0c;并赋予 root 权限。 演示站点&#xff1a;https://woniu336.github.io/ 魔改hugo主题: https://github.com/woniu336/hugo-magic 2. 服务器配置 建立 git 用户 adduser git安装 git sudo apt …...

【Datawhale AI夏令营第四期】 魔搭-大模型应用开发方向笔记 Task04 RAG模型 人话八股文Bakwaan_Buddy项目创空间部署

【Datawhale AI夏令营第四期】 魔搭-大模型应用开发方向笔记 Task04 RAG模型 人话八股文Bakwaan_Buddy项目创空间部署 什么是RAG&#xff1a; 我能把这个过程理解为Kimi.ai每次都能列出的一大堆网页参考资料吗&#xff1f;Kimi学了这些资料以后&#xff0c;根据这里面的信息综…...

CTF密码学小结

感觉没啥好总结的啊 基础的永远是RSA、流密码、哈希、对称密码、古典密码那一套&#xff08;密码学上过课都会&#xff09;&#xff0c;其他的就是数论的一些技巧 似乎格密码也很流行&#xff0c;以及一些奇奇怪怪的性质利用也很多 1、random设置种子后随机的性质&#xff1a…...

Vue快速入门(七)——Vue3 状态管理 - Pinia(二)

目录 六、核心概念——Getter 1、基本操作 定义getter 访问getter 2、访问其他 getter 3、向 getter 传递参数 4、访问其他 store 的 getter 使用 setup() 时的用法 使用选项式 API 的用法 使用 setup() 不使用 setup() 七、核心概念——Action 1、基本操作 定义a…...

Kylin V10 SP1桌面美化全攻略:从默认主题到个性化定制,让你的麒麟系统焕然一新

Kylin V10 SP1桌面美学革命&#xff1a;打造高效与美感兼具的麒麟系统工作空间 第一次打开Kylin V10 SP1系统时&#xff0c;那个默认的"寻光"主题确实给人一种清新简洁的感觉。但日复一日面对相同的界面&#xff0c;就像每天穿着同样的衣服上班——功能上没问题&…...

Video2X问答指南:用AI无损放大视频的10个常见问题解答

Video2X问答指南&#xff1a;用AI无损放大视频的10个常见问题解答 【免费下载链接】video2x A lossless video/GIF/image upscaler achieved with waifu2x, Anime4K, SRMD and RealSR. Started in Hack the Valley II, 2018. 项目地址: https://gitcode.com/GitHub_Trending/…...

人流后怎么吃恢复快?科学修护与饮食指南

引言&#xff1a;人流手术作为常见的妇科微创操作&#xff0c;术后身体修护与饮食调理直接影响恢复效果&#xff0c;也是女性关注的核心问题。不少女性在术后陷入“盲目食补”的误区&#xff0c;忽视了生殖系统损伤的精准修护&#xff0c;导致恢复周期延长、并发症风险升高。本…...

i.MX6ULL开发板无线SSH环境搭建指南

嵌入式开发板远程登录环境搭建指南1. 项目概述本技术文档详细记录了在基于i.MX6ULL处理器的嵌入式Linux开发板上搭建完整远程登录环境的实现方案。该方案包含三个核心组件&#xff1a;WiFi网络驱动移植、无线网络配置工具移植以及SSH服务部署。2. 硬件环境搭建2.1 WiFi模块选型…...

BepInEx Linux部署实战指南:从环境诊断到故障自愈

BepInEx Linux部署实战指南&#xff1a;从环境诊断到故障自愈 【免费下载链接】BepInEx Unity / XNA game patcher and plugin framework 项目地址: https://gitcode.com/GitHub_Trending/be/BepInEx 一、环境诊断&#xff1a;你的Linux系统准备好了吗&#xff1f; 为什…...

CentOS7系统维护终止后YUM源失效的解决方案

1. CentOS7维护终止带来的YUM源危机 去年夏天我给客户部署的CentOS7服务器突然无法安装新软件&#xff0c;屏幕上不断弹出"无法解析主机"的错误。这才意识到官方已经停止维护&#xff0c;默认的YUM源就像突然关门的超市&#xff0c;所有货架都空了。对于仍在使用Cent…...

别再为HackBar许可证发愁了!手把手教你用Burp Suite社区版完成同类测试

从HackBar到Burp Suite&#xff1a;安全测试工具的高效迁移指南 在Web安全测试领域&#xff0c;工具的选择往往决定了工作效率的上限。许多初级安全研究人员习惯使用HackBar这类轻量级浏览器插件进行快速测试&#xff0c;但当遇到功能限制或商业授权问题时&#xff0c;往往会陷…...

告别手动收集!用OWASP Amass自动化你的子域名侦察(附Kali/Windows/Mac安装配置)

从手工到自动化&#xff1a;OWASP Amass在子域名侦察中的高效实践 在网络安全领域&#xff0c;信息收集的质量和效率直接影响着后续渗透测试的成败。传统的手工子域名收集方式——在多个搜索引擎间切换、查询证书透明度日志、翻阅WHOIS记录——不仅耗时耗力&#xff0c;还容易…...

深入Linux tcpm框架:从FUSB302芯片看PD协议兼容性那些‘坑’

深入Linux tcpm框架&#xff1a;从FUSB302芯片看PD协议兼容性那些‘坑’ Type-C接口凭借其强大的供电能力和灵活的数据传输特性&#xff0c;已成为现代电子设备的标配。然而&#xff0c;在Linux系统中实现完美的PD协议兼容性&#xff0c;却是一场充满技术陷阱的冒险。本文将带您…...

VSCode调试ARM芯片:一份给硬件工程师的OpenOCD与J-Link配置清单

VSCode调试ARM芯片&#xff1a;一份给硬件工程师的OpenOCD与J-Link配置清单 当硬件工程师第一次将ARM Cortex-M开发板连接到电脑时&#xff0c;最令人沮丧的莫过于看着闪烁的LED却无法窥探芯片内部的运行状态。调试器就像硬件工程师的"听诊器"&#xff0c;而VSCode配…...