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

[SwiftUI 开发] 构建带有动画的图片瀑布流效果

在移动应用程序中,图片瀑布流布局是一种常见的设计模式,它不仅能够以网格的形式显示大量图片,还能允许用户点击图片进行全屏查看。
在下文中,将详细介绍如何使用 SwiftUI 构建一个带有点击动画效果的图片瀑布流布局,并通过 matchedGeometryEffect 实现图片从列表到全屏的平滑过渡。

效果概述

用户可以看到一个由多张图片组成的瀑布流布局,图片按列排列。当用户点击其中一张图片时,图片会在全屏模式下显示,并带有平滑的动画过渡。用户可以再次点击全屏图片,返回瀑布流视图。

核心技术点

  1. 瀑布流布局:使用 HStack 和 VStack 创建两列图片。
  2. 点击事件和动画过渡:通过 onTapGesture 实现点击事件,并使用 matchedGeometryEffect 实现动画效果。
  3. 全屏图片显示:使用 GeometryReader 调整全屏图片的布局,并在背景使用模糊效果。

实现步骤

1. 项目初始化

首先,在 Xcode 中创建一个新的 SwiftUI 项目。为了简单起见,我们在 ContentView 中实现所有功能。在实际项目中,你可以根据需求将代码拆分到多个视图中。

 

2. 构建基础的图片数据

假设我们有一组图片,命名为 "351" 到 "379"(假设这些图片资源已包含在项目中)。我们将这组图片存储在一个数组中。

struct ContentView: View {// 图片名称数组var imageNames = ["351", "352", "353", "354", "355", "356", "357", "358", "359", "360", "370", "371", "372", "373", "374", "375", "376", "377", "378", "379"]// 控制全屏展示图片的状态@State var show = false// 使用 @Namespace 修饰符定义动画作用域,用于 `matchedGeometryEffect` 共享动画效果@Namespace var animation// 当前被点击的图片名称@State var cItem = ""
  • imageNames:一个数组,用于存储图片的名称。
  • @State var show:一个布尔状态,控制是否显示全屏图片。
  • @Namespace var animation:命名空间,用于 matchedGeometryEffect 动画效果。
  • @State var cItem:存储当前被点击的图片名称。

 

3. 布局瀑布流图片

为了实现图片的瀑布流布局,我们将图片分成两列。使用 HStack 创建一个水平的图片容器,在其中嵌入两个 VStack 用于垂直排列图片。

var body: some View {// 使用 ScrollView 允许垂直滚动,隐藏滚动指示器ScrollView(showsIndicators: false) {// 两列图片的水平布局,使用 HStack 进行布局HStack(alignment: .top, spacing: 5) {// 第一列图片,使用数组的前一半createColumn(with: imageNames.prefix(imageNames.count / 2))// 第二列图片,使用数组的后一半createColumn(with: imageNames.suffix(imageNames.count / 2))}}.padding(.horizontal, 5) // 为 ScrollView 添加一些填充.overlay {if show {fullScreenImageOverlay // 全屏图片展示}}.edgesIgnoringSafeArea(.all) // 使图片铺满全屏
}

在这里我们使用 ScrollView 允许图片垂直滚动,并隐藏滚动指示器。HStack 将两列图片横向排列,padding(.horizontal, 5) 为整体视图添加左右间距。

 

4. 创建图片列

为了避免代码重复,我们将创建图片列的代码提取到一个函数中,这个函数通过传递图片名称数组的一部分来生成列布局。

// 创建列视图的函数,将图片数组传入,并通过 VStack 进行竖直排列
func createColumn(with items: ArraySlice<String>) -> some View {VStack(spacing: 5) {// 遍历图片名称数组,并为每张图片创建一个视图ForEach(items, id: \.self) { item inImage(item) // 显示图片.resizable() // 使图片可以调整大小.scaledToFill() // 保持图片比例并填充视图.matchedGeometryEffect(id: item, in: animation) // 绑定几何动画效果.frame(minWidth: 0, maxWidth: .infinity) // 最大宽度为可用空间的宽度.frame(maxHeight: .infinity) // 最大高度设为无限,允许视图扩展.cornerRadius(5) // 为图片添加圆角.onTapGesture {// 当图片被点击时,更新 cItem 为当前图片名称,并触发动画切换 show 状态cItem = itemwithAnimation(.spring()) {show = true // 切换全屏展示状态}}}}
}

主要说明

  • ForEach 用于遍历传入的图片数组并为每张图片创建视图。
  • Image(item) 加载图片,并使用 .resizable() 和 .scaledToFill() 保证图片适应视图大小。
  • matchedGeometryEffect 实现点击后图片动画的平滑过渡。
  • onTapGesture:当用户点击图片时,记录当前点击的图片名称,并将 show 状态改为 true 以显示全屏图片。

 

5. 全屏图片显示

当用户点击图片时,全屏展示该图片,并带有动画效果。我们使用 GeometryReader 以适应设备屏幕大小,并设置 matchedGeometryEffect 来确保图片从列表过渡到全屏时有平滑的动画效果。

// 全屏图片展示的视图,当 show 为 true 时显示
var fullScreenImageOverlay: some View {GeometryReader { geometry in// 通过几何读取器获取设备尺寸并动态调整图片大小Image(cItem) // 显示当前被点击的图片.resizable() // 使图片可以调整大小.scaledToFit() // 保持图片比例并适应全屏.matchedGeometryEffect(id: cItem, in: animation) // 绑定几何动画效果.frame(width: geometry.size.width, height: geometry.size.height) // 使用设备的宽高进行布局.background(.thinMaterial) // 使用薄模糊背景效果.onTapGesture {// 当全屏图片被点击时,切换 show 状态,退出全屏withAnimation(.spring()) {show = false}}}
}

在这里,我们使用 GeometryReader 读取设备的宽高,以调整全屏图片的大小,并确保其按比例适应屏幕。background(.thinMaterial) 为全屏图片设置了模糊背景效果,使用户的注意力集中在图片上。

 

6. 运行效果

最终实现的效果是:用户可以看到两列垂直排列的图片,点击任意图片时,该图片会平滑地过渡到全屏显示,并且背景会变为模糊效果,给用户带来沉浸式的视觉体验。再次点击全屏图片,图片会返回到原来的位置,并恢复到瀑布流布局。

 

结论

通过 SwiftUI 强大的布局和动画功能,我们可以轻松实现复杂的 UI 交互效果。matchedGeometryEffect 允许我们在不同视图之间创建共享的几何效果,保证动画的流畅性和一致性。而 GeometryReader 则让我们能够动态适应不同设备的屏幕大小。在这个示例中,完整地展示了如何构建一个功能强大且具有吸引力的图片瀑布流布局。

通过进一步优化代码和添加更多功能(如图片缩放、滑动关闭全屏等),你可以创建出更加丰富的用户体验。


http://www.mrgr.cn/news/20858.html

相关文章:

  • 1-7月NOA前装同比增长近2倍,理想/赛力斯/奔驰「领跑」
  • HyperWorks的RT功能及使用技巧
  • 应用方案 | 低功耗接地故障控制器D4145
  • win10任务栏颜色怎么调?分享几个简单操作,附上详细图文教程
  • Material xxx SDF Material doesn‘t have _Stencil property
  • AI艺术创作福利:免费领取红包封面,Meo喵、龙小金与你共庆佳节!
  • 动态面板模型
  • 解决 Ant Design Vue Upload 组件在苹果手机上只能拍照无法选择相册的问题
  • 解决 Transformer 根本缺陷,CoPE 论文爆火:所有大模型都能获得巨大改进!
  • 使用 nuxi init 创建全新 Nuxt 项目
  • 代码训练营 Day24 | 93.复原IP地址 |78.子集
  • 量化交易策略:中国市场的Carhart四因子模型python代码解析
  • 大牛直播SDK的RTSP直播播放器怎么样?
  • 【C题论文】2024数学建模国赛C题38页成品+配套所有小问代码+高清可视化结果图
  • 【日记】往哈尔滨西天取经、弱电工程师与软考证书(2113 字)
  • 【IEEE出版,IEEE Xplore等多数据库检索】第五届智能设计国际会议(ICID 2024,10月25-27)
  • VisualStudio环境搭建C++
  • Patlibc———更快捷的更换libc
  • 2024 年高教社杯全国大学生数学建模竞赛B题—生产过程中的决策问题(讲解+代码+成品论文助攻)
  • FreeRTOS学习笔记(一)初认RTOS