Flutter开发笔记 —— 图像缩略图功能实战

Flutter开发笔记 —— 图像缩略图功能实战

    • 插件应用列表
    • 效果图
    • 功能分析
      • scrollable_positioned_list插件应用
        • 滑动控制器
        • 滑动监听器
        • 应用
  • 结束语

大家在做图像浏览或部分关于图像的项目时,难免会遇到缩略图的相关功能,特地写了一个demo给大家进行分享,文笔一般,欢迎回复指正!。

插件应用列表

  • scrollable_positioned_list: ^0.3.8 (滑动处理)
  • flukit: ^3.0.1 (用来拿视图size)

效果图

thumb.gif

功能分析

视图主要以到 底图 + 侧边栏 + 动画三个方面,难度不大,可以自己自定义

视图相关代码

import 'dart:math';import 'package:flukit/flukit.dart';
import 'package:flutter/material.dart';
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
/*** @author Marinda* @date 2023/12/7 14:27* @description 缩略图实战*/
class ThumbComponentWidget extends StatefulWidget{const ThumbComponentWidget({super.key});State<StatefulWidget> createState() {return ThumbState();}}extension on String{String get assets{return "assets/$this";}
}/*** @author Marinda* @date 2023/12/7 14:28* @description 缩略图State*/
class ThumbState extends State<ThumbComponentWidget> with TickerProviderStateMixin{//平移late Animation<double> translationAnimation;late AnimationController controller;//底图路径String src =  "logo.jpg".assets;//缩略图列表List<String> imgList = ["logo.jpg".assets,"img2.jpg".assets,"img3.jpg".assets,"img4.jpg".assets,"logo.jpg".assets,"img2.jpg".assets,"img4.jpg".assets];void initState() {controller = AnimationController(vsync: this,duration: Duration(milliseconds: 300),reverseDuration: Duration(milliseconds: 300));translationAnimation = Tween<double>(begin: 0.0,end: 200).animate(controller);// TODO: implement initStatesuper.initState();}void readerLayout(RenderAfterLayout ral){screenSize = ral.size;}void dispose() {controller.dispose();// TODO: implement disposesuper.dispose();}Widget build(BuildContext context) {var size = MediaQuery.of(context).size;return Scaffold(appBar: AppBar(backgroundColor: Colors.blue,title: const Text("缩略图应用实战",style: TextStyle(color: Colors.white,fontSize: 20),),),body: Container(child: Stack(children: [//  底图显示Positioned(left: 0,right: 0,child: Container(width: size.width,height:size.height,decoration: BoxDecoration(image: DecorationImage(image: Image.asset("${src}",).image,fit: BoxFit.cover,filterQuality: FilterQuality.high)),),),//  遮罩层的缩略图Positioned(top: 0,left: 0,child: Visibility(child: InkWell(child: Container(width: size.width,height: size.height,color: Colors.black.withOpacity(.5),),onTap: (){controller.reverse();},),visible: true,),),//缩略图按钮Positioned(left: 0,top: size.height / 3,child: Container(child: Column(children: [InkWell(child: Container(decoration: BoxDecoration(color: Colors.grey,borderRadius: BorderRadius.only(topRight:Radius.circular(5),bottomRight: Radius.circular(5))),padding: EdgeInsets.only(left: 10,bottom: 5,top: 5,right: 10),child: Column(children: [Container(margin: EdgeInsets.only(bottom: 5),child: SizedBox(width: 30,height: 30,child: Image.asset("assets/thumb.png",fit: BoxFit.fill,color: Colors.white,),),),//文字Container(child: Text("缩略图",style: TextStyle(color: Colors.white,fontSize: 13),),)],),),onTap: (){controller.forward();},),],)),),//  遮罩层的缩略图Positioned(top: 0,left: 0,child: AnimatedBuilder(animation: controller,builder: (BuildContext context, Widget? child) {return Container(width: translationAnimation.value,height: size.height,color: Colors.white,padding: EdgeInsets.all(20),child: Stack(children: [//构建缩略图Container(color: Colors.white,child: ScrollablePositionedList.builder(itemCount: imgList.length,physics: BouncingScrollPhysics(),itemBuilder: (BuildContext context, int index) {var element = imgList[index];return AfterLayout(callback: readerLayout,child: InkWell(child: Container(// height: 100,padding: EdgeInsets.all(5),margin: EdgeInsets.only(bottom: 20),decoration: BoxDecoration(border: Border.all(color: Colors.grey.withOpacity(.5),width: 1),),child: Image.asset(element,fit: BoxFit.fill,),),onTap: ()=>changeImage(index),),);},),),Positioned(right: 10,top: size.height /2.5,child: InkWell(child: SizedBox(width: 30,height: 30,child: Transform.rotate(angle: pi * 1.5,child: Image.asset("assets/hide.png",fit: BoxFit.fill,),),),onTap: (){controller.reverse();},),)],),);},),)],),),);}}

关于列表渲染这一块没有使用SingleChildScroll或者ListView

而是使用了ScrollablePositionedList作为渲染父组件

scrollable_positioned_list插件应用

这是一款很优秀的插件,本文以分享为主给大家简单解析。


插件地址:https://pub.dev/packages/scrollable_positioned_list


我们来简单讲讲为什么使用这个插件

根据官方插件文献可以得知相较于传统滑动控制处理。

该插件中拥有可以根据索引页跳转相对位置偏移量跳转,传统方式还需要计算position点位信息,相比较为麻烦,感兴趣的可以自己去插件文献看看。

滑动控制器

我们接下来会使用到以下两个控制器做滑动跳转处理。

  • ItemScrollController (项目滑动控制器)
  • ScrollOffsetController (滑动偏移量控制器)

ItemScrollController 主要以索引号进行跳转控制

ScrollOffsetContainer 主要以相对位置偏移量做跳转控制

滑动监听器

接下来是配套的滑动监听器

  • ItemPositionsListener (监听滑动后的可视视图列表)
  • ScrollOffsetListener (监听滑动后的具体滑动值)

ItemPositionsListener 主要监听以滑动后当前可视范围内的所有项目点位信息列表
ScrollOffsetListener 主要监听当前滑动的滑动总值,用来方便做点位计算

应用

使用到的相关控制器和监听器讲完了,我们来看看具体实现方法

定义相关控制器和监听器以及变量


List<ItemPosition> visibleItemViewList = [];
Size viewScreenSize = Size.zero;
double scrollDetails = 0;
Size screenSize = Size.zero;
ItemScrollController itemScrollController = ItemScrollController();
final ItemPositionsListener itemPositionsListener = ItemPositionsListener.create();
ScrollOffsetListener scrollOffsetListener = ScrollOffsetListener.create();
ScrollOffsetController scrollOffsetController = ScrollOffsetController();

绑定控制器和监听器

ScrollablePositionedList.builder(itemCount: imgList.length,itemPositionsListener: itemPositionsListener,scrollOffsetListener: scrollOffsetListener,scrollOffsetController: scrollOffsetController,physics: BouncingScrollPhysics(),itemScrollController: itemScrollController,itemBuilder: (BuildContext context, int index) {var element = imgList[index];return AfterLayout(callback: readerLayout,child: InkWell(child: Container(// height: 100,padding: EdgeInsets.all(5),margin: EdgeInsets.only(bottom: 20),decoration: BoxDecoration(border: Border.all(color: Colors.grey.withOpacity(.5),width: 1),),child: Image.asset(element,fit: BoxFit.fill,),),onTap: ()=>changeImage(index),),);},
)

initState中进行初始化控制

//做滑动视图监听处理
itemPositionsListener.itemPositions.addListener(() {//储存可视范围内的点位信息列表var list = itemPositionsListener.itemPositions.value.toList();visibleItemViewList = list;
});
//滑动点位值
scrollOffsetListener.changes.listen((event) {scrollDetails += event;
});

目前我们已经拿到了可视范围内的点位列表&滑动总值,接下来处理切换图像

changeImage方法

/** @author Marinda* @date 2023/12/7 15:42* @description 修改图像*/
changeImage(int index){var element =imgList[index];var target = visibleItemViewList.firstWhere((element) => element.index == index);//不可见底部内容if(target.itemTrailingEdge >=1.0){//边距double step = 30;double value = screenSize.height - step;scrollOffsetController.animateScroll(offset: value, duration: Duration(milliseconds: 300));}//边界处理if(target.itemLeadingEdge <=0.0){itemScrollController.scrollTo(index: index, duration: Duration(milliseconds: 300));}src = element;setState(() {});
}

ItemPosition(项目点位)下的两个参数值简单讲讲

  • itemTrailingEdge (在可视区域范围内尾部可视的比例)
  • itemLeadingEdge (在可视区域范围内首部可视的比例)

感兴趣的可以自己看看注释,这是我所理解下来的意思,不对欢迎指正!

上文判断意思:

  • 如果 itemTrailingEdge值大于等于1了,则当前只能看到尾部Item的一半或者少许
  • 如果 itemLeadingEdge的值小于等于0了,则当前只能看到首部Item的一半或者少许

结束语

功能到这里就结束了,如果有不对的地方或者建议欢迎指正,感谢你的观看!

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

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

相关文章

从浅入深掌握进阶结构体(C语言)

前言 这一期我们将继续讲解结构体的知识&#xff0c;还没有看过上一期的小伙伴一定要赶紧去学习哦。 上一期&#xff0c;冲鸭&#xff01; 那么话不多说我们开始今天的学习吧&#xff01; 文章目录 1,结构体的自引用2,匿名结构体3,位段4,结构体的传参5,尾声 1,结构体的自引用 …

数据库备份脚本

#!/bin/bash #数据库备份 #工具&#xff1a;xtrabackupif [ ! -d /xtrabackup/ ];thenmkdir /xtrabackup/{full,inter,diff} -p fito_mail15191876750163.com db_userroot db_passwdAren123 basedir/xtrabackup/full/ baseinter/xtrabackup/inter/ basediff/xtrabackup/diff/ f…

【SSM源码】基于JAVA的高校竞赛和考级查询系统

该项目含有源码、文档、PPT、配套开发软件、软件安装教程、项目发布教程等学习内容。 目录 一、项目介绍&#xff1a; 二、文档学习资料&#xff1a; 三、模块截图&#xff1a; 四、开发技术与运行环境&#xff1a; 五、代码展示&#xff1a; 六、数据库表截图&#xff1a…

uniapp-hubildx配置

1.配置浏览器 &#xff08;1&#xff09;运行》运行到浏览器配置》配置web服务器 &#xff08;2&#xff09;选择浏览器安装路径 &#xff08;3&#xff09;浏览器安装路径&#xff1a; &#xff08;3.1&#xff09; 右键点击图标》属性 &#xff08;3.2&#xff09;选择目标&…

系统设计-微服务架构

典型的微服务架构图 下图展示了一个典型的微服务架构。 负载均衡器&#xff1a;它将传入流量分配到多个后端服务。CDN&#xff08;内容交付网络&#xff09;&#xff1a;CDN 是一组地理上分布的服务器&#xff0c;用于保存静态内容以实现更快的交付。客户端首先在 CDN 中查找内…

《opencv实用探索·十四》VideoCapture播放视频和视像头调用

1、VideoCapture播放视频 #include <opencv2/opencv.hpp> #include <iostream>using namespace std; using namespace cv;int main() {// 定义相关VideoCapture对象VideoCapture capture;// 打开视频文件capture.open("1.avi");// 判断视频流读取是否正…

案例064:基于微信小程序的考研论坛设计

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;SSM JDK版本&#xff1a;JDK1.8 数据库&#xff1a;mysql 5.7 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.5.4 小程序框架&#xff1a;uniapp 小程序开发软件&#xff1a;HBuilder X 小程序…

问题:batchnormal训练单个batch_size就会报错吗

Batch Normalization&#xff08;批标准化&#xff09;是一种深度学习中的正则化技巧&#xff0c;它可以改进网络的训练过程。在训练神经网络时&#xff0c;Batch Normalization可以帮助解决内部协变量偏移&#xff08;Internal Covariate Shift&#xff09;的问题。 在标准的…

软件测试--selenium安装使用

安装selenium不少人使用pip命令来安装selenium&#xff0c;辛辛苦苦安装完之后&#xff0c;还是不能使用。所以我们可以是直接使用编译器&#xff0c;pycharm直接安装selenium扩展包。 file中点击settings 在Settings中点击Project Interpreter,点击加号就可以安装各种需要的扩…

Docker安装postgres最新版

1. postgres数据库 PostgreSQL是一种开源的关系型数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;它是一种高度可扩展的、可靠的、功能丰富的数据库系统。以下是关于PostgreSQL的一些介绍&#xff1a; 开源性&#xff1a;PostgreSQL是一个开源项目&#xff0c;可以…

One-to-Few Label Assignment for End-to-End Dense Detection阅读笔记

One-to-Few Label Assignment for End-to-End Dense Detection阅读笔记 Abstract 一对一&#xff08;o2o&#xff09;标签分配对基于变换器的端到端检测起着关键作用&#xff0c;最近已经被引入到全卷积检测器中&#xff0c;用于端到端密集检测。然而&#xff0c;o2o可能因为…

docker镜像仓库hub.docker.com无法访问

docker镜像仓库hub.docker.com无法访问 文章主要内容&#xff1a; 介绍dockerhub为什么无法访问解决办法 1 介绍dockerhub为什么无法访问 最近许多群友都询问为什么无法访问Docker镜像仓库&#xff0c;于是我也尝试去访问&#xff0c;结果果然无法访问。 大家的第一反应就是…

flutter开发实战-ValueListenableBuilder实现局部刷新功能

flutter开发实战-ValueListenableBuilder实现局部刷新功能 在创建的新工程中&#xff0c;点击按钮更新counter后&#xff0c;通过setState可以出发本类的build方法进行更新。当我们只需要更新一小部分控件的时候&#xff0c;通过setState就不太合适了&#xff0c;这就需要进行…

MQTT协议对比TCP网络性能测试模拟弱网测试

MQTT正常外网压测数据---时延diff/ms如下图&#xff1a; MQTT弱网外网压测数据 TCP正常外网压测数据 TCP弱网外网压测数据 结论&#xff1a;

这些接口自动化测试工具如果不知道,就真out了!

一、Postman Postman是一款广受欢迎的API测试工具&#xff0c;除了手动发送HTTP请求的基本功能&#xff0c;它还提供了自动化测试和脚本测试的功能&#xff0c;非常适合进行HTTP接口的自动化测试。 二、Rest-Assured Rest-Assured是一个Java库&#xff0c;专为REST服务的测试…

craco + webpack 4 升 5

craco webpack 4 升 5 更新包版本尝试build升级其他依赖库使用process插件打印进度信息到底需要多少内存分析构建产出添加 splitChunk总结记录一些好文章&#xff1a; 我的项目使用 craco react 开发 我的 package.json {// ......"dependencies": {"ant-desi…

WebSocket入门介绍及编程实战

HTTP的限制 全双工和半双工&#xff1a; 全双工&#xff1a;全双工&#xff08;Full Duplex&#xff09;是允许数据在两个方向上同时传输。 半双工&#xff1a;半双工&#xff08;Half Duplex&#xff09;是允许数据在两个方向上传输&#xff0c;但是同一个时间段内只允许一个…

为什么每个 Java 开发者都需要了解 Scala

前面我们一起回顾了第九期 Scala & Java Meetup 中最受关注的话题 —— jdk 并发编程的终极解决方案&#xff1a;虚拟线程&#xff0c;探讨了这一新特性对包括 Scala 在内的响应式编程语言的影响。 本次 Meetup 的首位分享者 Chunsen&#xff0c;在加入 Tubi 成为 Scala 开…

微服务实战系列之J2Cache

前言 经过近几天陆续发布Cache系列博文&#xff0c;博主已对业界主流的缓存工具进行了基本介绍&#xff0c;当然也提到了一些基本技巧。相信各位盆友看见这么多Cache工具后&#xff0c;在选型上一定存在某些偏爱&#xff1a; A同学说&#xff1a;不管业务千变万化&#xff0c;…

Linux环境下ARM开发

目录 前言ARM启动及开发基础1.Cortex-A架构2.启动方式3.汇编基础4.Makefile语法基础5.Makefile补充6.编译下载 结语 前言 主要介绍基于linux开发环境下&#xff0c;如何开发ARM A7 ARM启动及开发基础 1.Cortex-A架构 1&#xff09;Cortex-A7运行模式 模式说明User(USR)用户模…