flutter开发实战-轮播Swiper更改Custom_layout样式中Widget层级

flutter开发实战-轮播Swiper更改Custom_layout样式中Widget层级

在之前的开发过程中,需要实现卡片轮播效果,但是卡片轮播需要中间大、两边小一些的效果,这里就使用到了Swiper。具体效果如视频所示
添加链接描述
这里需要的效果是中间大、两边小一些,中间的卡片在最上层,两边的卡片会被中间的卡片挡住一部分。所以需要处理一下Custom_layout样式中Widget层级关系。
在这里插入图片描述

一、引入Swiper

在工程的pubspec.yaml中引入swiper

  # 轮播图flutter_swiper_null_safety: ^1.0.2

二、Swiper使用

Swiper无限轮播

通过Swiper()来构建轮播图控件,可以同步不同的属性搭配不同的效果

默认效果

Container(height: 200,child: new Swiper(itemBuilder: (BuildContext context,int index){return new Image.network(imgs[index],fit: BoxFit.cover,);},itemCount: imgs.length,pagination: new SwiperPagination(),//如果不填则不显示指示点control: new SwiperControl(),//如果不填则不显示左右按钮),
),

3D卡片滚动

Container(height:  200,child: new Swiper(itemBuilder: (BuildContext context, int index) {return new Image.network(imgs[index],fit: BoxFit.cover,);},itemCount: imgs.length,viewportFraction: 0.8,scale: 0.9,),
),

无限卡片堆叠

Container(height: 200,child: new Swiper(itemBuilder: (BuildContext context, int index) {return new Image.network(imgs[index],fit: BoxFit.cover,);},itemCount: imgs.length,itemWidth: 300.0,layout: SwiperLayout.STACK,),
),

无限卡片堆叠2

Container(height: 200,child: new Swiper(itemBuilder: (BuildContext context, int index) {return new Image.network(imgs[index],fit: BoxFit.cover,);},itemCount: imgs.length,itemWidth: 300.0,itemHeight: 300.0,layout: SwiperLayout.TINDER,),
),

自定义效果

Container(height: 200,child: new Swiper(layout: SwiperLayout.CUSTOM,customLayoutOption: new CustomLayoutOption(startIndex: -1,stateCount: 3).addRotate([-45.0/180,0.0,45.0/180]).addTranslate([new Offset(-370.0, -40.0),new Offset(0.0, 0.0),new Offset(370.0, -40.0)]),itemWidth: 300.0,itemHeight: 200.0,itemBuilder: (context, index) {return new Image.network(imgs[index],fit: BoxFit.cover,);},itemCount: imgs.length),
)

三、更改Custom_layout样式中Widget层级

需要的效果是中间大、两边小一些,中间的卡片在最上层,两边的卡片会被中间的卡片挡住一部分

这里使用的是SwiperLayout.CUSTOM,

这里就需要查看源码,更改Custom_layout样式中Widget层级关系,更改Stack的子Widget层级关系,需要调整中间的卡片在最上层。

找到Custom_layout.dart的源码,找到Widget _buildAnimation(BuildContext context, Widget? w)。

需要更改list,重新排列list

if (list.isNotEmpty) {int length = list.length;int mid = length~/2;List<Widget> transList = [];for (int i = mid; i >= 0; i--) {List<Widget> subList = [];for (int index = 0; index < length; index++) {int abs = (index - mid).abs();if (abs == i) {subList.add(list[index]);}}transList.addAll(subList);}print("transList:${transList}");if (transList.isNotEmpty && transList.length == list.length) {list = transList;}}

更改后的_buildAnimation代码如下

Widget _buildAnimation(BuildContext context, Widget? w) {List<Widget> list = [];if (_animationCount != null) {double? animationValue = _animation?.value;for (int i = 0; i < _animationCount!; ++i) {int realIndex = _currentIndex + i + (_startIndex ?? 0);realIndex = realIndex % widget.itemCount;if (realIndex < 0) {realIndex += widget.itemCount;}if (animationValue != null) {list.add(_buildItem(i, realIndex, animationValue));}}}if (list.isNotEmpty) {int length = list.length;int mid = length~/2;List<Widget> transList = [];for (int i = mid; i >= 0; i--) {List<Widget> subList = [];for (int index = 0; index < length; index++) {int abs = (index - mid).abs();if (abs == i) {subList.add(list[index]);}}transList.addAll(subList);}print("transList:${transList}");if (transList.isNotEmpty && transList.length == list.length) {list = transList;}}return new GestureDetector(behavior: HitTestBehavior.opaque,onPanStart: _onPanStart,onPanEnd: _onPanEnd,onPanUpdate: _onPanUpdate,child: new ClipRect(child: new Center(child: _buildContainer(list),),),);}

四、实现中间大、两边小一些,中间的卡片在最上层,两边的卡片会被中间的卡片挡住的效果

需要实现效果的时候,我们需要使用Swiper的custom,使用CustomLayoutOption添加addScale和addOpacity以及addTranslate来确定不同的卡片的缩放大小、透明度、以及offset

代码如下

Swiper(autoplay: true,layout: SwiperLayout.CUSTOM,customLayoutOption:CustomLayoutOption(startIndex: 0, stateCount: 5)..addScale([0.6,0.8,1.0,0.8,0.6,], Alignment.center)..addOpacity([1.0,1.0,1.0,1.0,1.0,])..addTranslate([Offset(-180.0, 0),Offset(-80.0, 0),Offset(0.0, 0.0),Offset(80.0, 0),Offset(180.0, 0),]),itemWidth: 230.0,itemHeight: 230.0,itemBuilder: (context, index) {return SwiperCard(imageUrl: imageUrls[index]);},itemCount: imageUrls.length,)

页面的完整代码如下

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_swiper_null_safety/flutter_swiper_null_safety.dart';class SwiperPage extends StatefulWidget {const SwiperPage({super.key});@overrideState<SwiperPage> createState() => _SwiperPageState();
}class _SwiperPageState extends State<SwiperPage> {List<String> imageUrls = [];@overridevoid initState() {// TODO: implement initStateimageUrls = ["https://d-ssl.dtstatic.com/uploads/blog/202301/08/20230108192142_ff632.thumb.1000_0.jpeg_webp","https://d-ssl.dtstatic.com/uploads/blog/202301/08/20230108192143_f4355.thumb.1000_0.jpeg_webp","https://d-ssl.dtstatic.com/uploads/blog/202301/08/20230108192146_0aaf2.thumb.1000_0.jpeg_webp","https://d-ssl.dtstatic.com/uploads/blog/202301/08/20230108192148_357ff.thumb.1000_0.jpeg_webp","https://d-ssl.dtstatic.com/uploads/blog/202301/08/20230108192149_92c71.thumb.1000_0.jpeg_webp"];super.initState();}@overridevoid dispose() {// TODO: implement disposesuper.dispose();}@overrideWidget build(BuildContext context) {Size screenSize = MediaQuery.of(context).size;return Scaffold(appBar: AppBar(title: const Text('SwiperPage'),),body: Container(width: screenSize.width,height: screenSize.height,child: Stack(alignment: Alignment.center,children: [Swiper(autoplay: true,layout: SwiperLayout.CUSTOM,customLayoutOption:CustomLayoutOption(startIndex: 0, stateCount: 5)..addScale([0.6,0.8,1.0,0.8,0.6,], Alignment.center)..addOpacity([1.0,1.0,1.0,1.0,1.0,])..addTranslate([Offset(-180.0, 0),Offset(-80.0, 0),Offset(0.0, 0.0),Offset(80.0, 0),Offset(180.0, 0),]),itemWidth: 230.0,itemHeight: 230.0,itemBuilder: (context, index) {return SwiperCard(imageUrl: imageUrls[index]);},itemCount: imageUrls.length,)],),),);}
}class SwiperCard extends StatelessWidget {const SwiperCard({super.key,required this.imageUrl,});final String imageUrl;@overrideWidget build(BuildContext context) {return Container(width: 230,height: 230,clipBehavior: Clip.hardEdge,decoration: BoxDecoration(color: Colors.white,borderRadius: BorderRadius.all(Radius.circular(10),),border: Border.all(color: Color(0xFF5C6BC0),style: BorderStyle.solid,width: 3,),boxShadow: [BoxShadow(color: Color(0xFFE8EAF6),offset: Offset(0, -5),blurRadius: 10,)],),child: Stack(alignment: Alignment.center, children: [Positioned(top: 0,child: Image.network(imageUrl,width: 230,height: 230,),),]),);}
}

最终实现了效果。

五、小结

flutter开发实战-轮播Swiper更改Custom_layout样式中Widget层级

学习记录,每天不停进步。

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

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

相关文章

No matching version found for @babel/compat-data@^7.23.5 处理

npm ERR! notarget No matching version found for babel/compat-data^7.23.5 处理 报错信息 npm WARN ERESOLVE overriding peer dependency npm ERR! code ETARGET npm ERR! notarget No matching version found for babel/compat-data^7.23.5. npm ERR! notarget In most …

变速箱壳体铸造件自动化三维测量室厂家自动化检测偏差比对-CASAIM-IS(2ND)

一、背景介绍&#xff1a; 随着制造业的快速发展&#xff0c;对产品质量和生产效率的要求不断提高。壳体铸造件作为一种常见的机械零部件&#xff0c;广泛应用于各个领域&#xff0c;对壳体铸造件的质量可靠性的要求也越来越高&#xff0c;因此&#xff0c;对壳体铸造件进行精…

单链表相关经典算法OJ题:移除链表元素

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 题目&#xff1a;移除链表元素 解法一&#xff1a; 解法一的代码实现&#xff1a; 解法二&#xff1a; 解法二代码的实现&#xff1a; 总结 前言 世上有两种耀眼的…

Python 进阶(十二):随机数(random 模块)

《Python入门核心技术》专栏总目录・点这里 文章目录 1. 导入random库2. 常用随机数函数2.1 生成随机浮点数2.2 生成随机整数2.3 从序列中随机选择2.4 随机打乱序列3. 设置随机数种子4. 应用实例4.1 游戏开发4.2 数据分析4.3 加密与安全4.4 模拟实验5. 总结大家好,我是水滴~~ …

长沙电信大楼火灾调查报告发布:系烟头引发。FIS来护航安全

近日&#xff0c;长沙电信大楼的火灾调查报告引起广泛关注。调查发现&#xff0c;火灾是由未熄灭的烟头引发&#xff0c;烟头点燃了室外平台的易燃物&#xff0c;迅速蔓延至整个建筑。这起悲剧再次提醒我们&#xff0c;小小的疏忽可能酿成大灾难。但如果我们能及时发现并处理这…

Git常用命令#merge分支合并

要查看所有分支&#xff0c;包括本地和远程仓库的分支&#xff0c;可以使用以下命令&#xff1a; 1.查看分支 1.1 查看本地分支 git branch这个命令会列出本地所有的分支&#xff0c;当前所在的分支会有 * 标记。 1.2 查看远程分支 git branch -r这个命令会列出远程仓库的分…

XUbuntu22.04之安装OBS30.0强大录屏工具(一百九十五)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

邮政快递物流查询,将指定某天签收的单号筛选出来

批量查询邮政快递单号的物流信息&#xff0c;将指定某天签收的单号筛选出来。 所需工具&#xff1a; 一个【快递批量查询高手】软件 邮政快递单号若干 操作步骤&#xff1a; 步骤1&#xff1a;运行【快递批量查询高手】软件&#xff0c;并登录 步骤2&#xff1a;点击主界面左…

HarmonyOS4.0 ArkUI组件

目录 简介 搭建开发环境 ArkUI基础组件 Image组件 Text组件 TextInput Button Slider 简介 HarmonyOS 4.0的ArkUI组件是一套UI开发框架&#xff0c;提供开发者进行应用UI开发时所必须的能力。在ArkUI中&#xff0c;组件是界面搭建与显示的最小单位&#xff0c;开发者通过…

Redis7--基础篇5(管道、发布订阅)

管道是什么 管道(pipeline)可以一次性发送多条命令给服务端&#xff0c;服务端依次处理完完毕后&#xff0c;通过一条响应一次性将结果返回&#xff0c;通过减少客户端与redis的通信次数来实现降低往返延时时间。pipeline实现的原理是队列&#xff0c;先进先出特性就保证数据的…

基于STC12C5A60S2系列1T 8051单片机的液晶显示器LCD1602显示整数、小数应用

基于STC12C5A60S2系列1T 8051单片机的液晶显示器LCD1602显示整数、小数应用 STC12C5A60S2系列1T 8051单片机管脚图STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式及配置STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式介绍液晶显示器LCD1602简单介绍IIC通信简单介绍…

IP地址的地理位置:固定性与动态性的平衡

IP地址的地理位置是网络通信中一个重要的元素&#xff0c;常被用于定位设备和用户。然而&#xff0c;很多人好奇&#xff0c;IP地址的地理位置是否会发生变化&#xff1f;本文将深入讨论IP地址地理位置的固定性与动态性之间的平衡&#xff0c;以及造成这种变化的因素。 1. IP地…