Swift - 使用CollectionView实现图片Gallery画廊效果(左右滑动浏览图片)
1,效果图

2,画廊布局类:LinearCollectionViewLayout
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
import UIKitclass LinearCollectionViewLayout: UICollectionViewFlowLayout { //元素宽度 var itemWidth:CGFloat = 100 //元素高度 var itemHeight:CGFloat = 100 //对一些布局的准备操作放在这里 override func prepare() { super.prepare() //设置元素大小 self.itemSize = CGSize(width: itemWidth, height: itemHeight) //设置滚动方向 self.scrollDirection = .horizontal //设置间距 self.minimumLineSpacing = self.collectionView!.bounds.width / 2 - itemWidth //设置内边距 //左右边距为了让第一张图片与最后一张图片出现在最中央 //上下边距为了让图片横行排列,且只有一行 let left = (self.collectionView!.bounds.width - itemWidth) / 2 let top = (self.collectionView!.bounds.height - itemHeight) / 2 self.sectionInset = UIEdgeInsetsMake(top, left, top, left) } //边界发生变化时是否重新布局(视图滚动的时候也会触发) //会重新调用prepareLayout和调用 //layoutAttributesForElementsInRect方法获得部分cell的布局属性 override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool { return true } //rect范围下所有单元格位置属性 override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? { //从父类得到默认的所有元素属性 let array = super.layoutAttributesForElements(in: rect) //可见区域(目前显示出来的位于collection view上的矩形区域) let visiableRect = CGRect(x: self.collectionView!.contentOffset.x, y: self.collectionView!.contentOffset.y, width: self.collectionView!.frame.width, height: self.collectionView!.frame.height) //当前屏幕中点,相对于collect view上的x坐标 let centerX = self.collectionView!.contentOffset.x + self.collectionView!.bounds.width / 2 //这个是为了计算缩放比例的 let maxDeviation = self.collectionView!.bounds.width / 2 + itemWidth / 2 for attributes in array! { //与可见区域做碰撞,如果该单元格没显示则直接跳过 if !visiableRect.intersects(attributes.frame) {continue} //显示的单元根据偏移量决定放大倍数(最大放大1.8倍,而离屏幕中央越远的单元格缩放的越小) let scale = 1 + (0.8 - abs(centerX - attributes.center.x) / maxDeviation) attributes.transform = CGAffineTransform(scaleX: scale, y: scale) } return array } /** 用来设置collectionView停止滚动那一刻的位置(实现目的是当停止滑动,时刻有一张图片是位于屏幕最中央的) proposedContentOffset: 原本collectionView停止滚动那一刻的位置 velocity:滚动速度 返回:最终停留的位置 */ override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint { //停止滚动时的可见区域 let lastRect = CGRect(x: proposedContentOffset.x, y: proposedContentOffset.y, width: self.collectionView!.bounds.width, height: self.collectionView!.bounds.height) //当前屏幕中点,相对于collect view上的x坐标 let centerX = proposedContentOffset.x + self.collectionView!.bounds.width * 0.5; //这个可见区域内所有的单元格属性 let array = self.layoutAttributesForElements(in: lastRect) //需要移动的距离 var adjustOffsetX = CGFloat(MAXFLOAT); for attri in array! { //每个单元格里中点的偏移量 let deviation = attri.center.x - centerX //保存偏移最小的那个 if abs(deviation) < abs(adjustOffsetX) { adjustOffsetX = deviation } } //通过偏移量返回最终停留的位置 return CGPoint(x: proposedContentOffset.x + adjustOffsetX, y: proposedContentOffset.y) }} |
3,使用样例

|
1
2
3
4
5
6
7
8
9
10
11
12
|
import UIKit//自定义的Collection View单元格class MyCollectionViewCell: UICollectionViewCell { //用于显示图片 @IBOutlet weak var imageView: UIImageView! override func awakeFromNib() { super.awakeFromNib() }} |
(2)主视图代码
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
import UIKitclass ViewController: UIViewController { //普通的flow流式布局 var flowLayout:UICollectionViewFlowLayout! //自定义的线性布局 var linearLayput:LinearCollectionViewLayout! var collectionView:UICollectionView! //重用的单元格的Identifier let CellIdentifier = "myCell" //所有书籍数据 var images = ["c#.png", "html.png", "java.png", "js.png", "php.png", "react.png", "ruby.png", "swift.png", "xcode.png"] override func viewDidLoad() { super.viewDidLoad() //初始化Collection View initCollectionView() //注册tap点击事件 let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(ViewController.handleTap(_:))) collectionView.addGestureRecognizer(tapRecognizer) } private func initCollectionView() { //初始化flow布局 flowLayout = UICollectionViewFlowLayout() flowLayout.itemSize = CGSize(width: 60, height: 60) flowLayout.sectionInset = UIEdgeInsets(top: 74, left: 0, bottom: 0, right: 0) //初始化自定义布局 linearLayput = LinearCollectionViewLayout() //初始化Collection View collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: linearLayput) //Collection View代理设置 collectionView.delegate = self collectionView.dataSource = self collectionView.backgroundColor = .white //注册重用的单元格 let cellXIB = UINib.init(nibName: "MyCollectionViewCell", bundle: Bundle.main) collectionView.register(cellXIB, forCellWithReuseIdentifier: CellIdentifier) //将Collection View添加到主视图中 view.addSubview(collectionView) } //点击手势响应 func handleTap(_ sender:UITapGestureRecognizer){ if sender.state == UIGestureRecognizerState.ended{ let tapPoint = sender.location(in: self.collectionView) //点击的是单元格元素 if let indexPath = self.collectionView.indexPathForItem(at: tapPoint) { //通过performBatchUpdates对collectionView中的元素进行批量的插入,删除,移动等操作 //同时该方法触发collectionView所对应的layout的对应的动画。 self.collectionView.performBatchUpdates({ () -> Void in self.collectionView.deleteItems(at: [indexPath]) self.images.remove(at: indexPath.row) }, completion: nil) } //点击的是空白位置 else{ //新元素插入的位置(开头) let index = 0 images.insert("xcode.png", at: index) self.collectionView.insertItems(at: [IndexPath(item: index, section: 0)]) } } } //切换布局样式 @IBAction func changeLayout(_ sender: Any) { self.collectionView.collectionViewLayout.invalidateLayout() //交替切换新布局 let newLayout = collectionView.collectionViewLayout .isKind(of: LinearCollectionViewLayout.self) ? flowLayout : linearLayput collectionView.setCollectionViewLayout(newLayout!, animated: true) } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() }}//Collection View数据源协议相关方法extension ViewController: UICollectionViewDataSource { //获取分区数 func numberOfSections(in collectionView: UICollectionView) -> Int { return 1 } //获取每个分区里单元格数量 func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return images.count } //返回每个单元格视图 func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { //获取重用的单元格 let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CellIdentifier, for: indexPath) as! MyCollectionViewCell //设置内部显示的图片 cell.imageView.image = UIImage(named: images[indexPath.item]) return cell }}//Collection View样式布局协议相关方法extension ViewController: UICollectionViewDelegate { } |
源码下载:
hangge_1602.zip
原文出自:www.hangge.com 转载请保留原文链接:http://www.hangge.com/blog/cache/detail_1602.html
Swift - 使用CollectionView实现图片Gallery画廊效果(左右滑动浏览图片)的更多相关文章
- Android BaseAdapter Gallery 画廊视图 (左右拖动图片列表拖至中间时图片放大显示)
画廊视图使用Gallery表示,能够按水平方向显示内容,并且可以手指直接拖动图片和移动,一般用来浏览图片,,被选中的选项位于中间,并且可以响应事件显示信息.在使用画廊视图时,首先在屏幕上添加Galle ...
- wpf 模拟3D效果(和手机浏览图片效果相似)(附源码)
原文 wpf 模拟3D效果(和手机浏览图片效果相似)(附源码) pf的3D是一个很有意思的东西,类似于ps的效果,类似于电影动画的效果,因为动画的效果,(对于3D基础的摄像机,光源,之类不介绍,对于依 ...
- RecyclerView实现Gallery画廊效果
使用RecyclerView实现一个画廊效果,主要是使用support库中最新加入的PagerSnapHelper类,通过计算滑动偏移来计算scale的值. 基本实现 首先需要为RecyclerVie ...
- RecyclerView 实现gallery画廊效果
1.RecyclerView的基本用法 首先主Activity的布局文件: [html] view plaincopy <RelativeLayout xmlns:android="h ...
- Android 自定义View 之利用ViewPager 实现画廊效果(滑动放大缩小)
http://www.2cto.com/kf/201608/542107.html
- UI组件之AdapterView及其子类(四)Gallery画廊控件使用
听说 Gallery如今已经不使用了,API使用ViewPaper取代了,以后再学专研ViewPaper吧如今说说Gallery画廊,就是不停显示图片的意思 Gallery是用来水平滚动的显示一系列项 ...
- js 实现图片瀑布流效果,可更改配置参数 带完整版解析代码[waterFall.js]
前言: 本人纯小白一个,有很多地方理解的没有各位大牛那么透彻,如有错误,请各位大牛指出斧正!小弟感激不尽. 本篇文章为您分析一下原生JS实现图片瀑布流效果 页面需求 1 ...
- Swift 使用CollectionView 实现图片轮播封装就是这样简单
前言: 这篇你可以学会自定义视图,创建collectionView,协议的使用,定时器; 自制图片 先上Demo:Github上封装好的下载即用, 好用请Star Thanks首先新建一个继承于UIV ...
- 第31讲 UI组件之 Gallery画廊控件
第31讲 UI组件之 Gallery画廊控件 1.Gallery的简介 Gallery(画廊)是一个锁定中心条目并且拥有水平滚动列表的视图,一般用来浏览图片,并且可以响应事件显示信息.Gallery只 ...
随机推荐
- OpenCV+VS 2015开发环境配置
最近跑C程序,头文件中用到了OpenCV中的文件,找了很多篇OpenCV+VS的环境配置,发现如下这篇写的最为详细,特转载来自己的博客中留存,并附上原博客地址如下 OpenCV学习笔记(一)——Ope ...
- Hadoop MapReduce编程 API入门系列之wordcount版本3(七)
这篇博客,给大家,体会不一样的版本编程. 代码 package zhouls.bigdata.myMapReduce.wordcount3; import java.io.IOException; i ...
- 单元测试之Mock
为什么需要Mock. 真实对象具有不确定的行为.所以会产生不可预测的结果. 真实对象很难被创建. 真实对象的某些行为很难被触发(如网络错误). 真实对象令程序的运行速度很慢. 真实对象有(或者是)用户 ...
- redis启动出错 Creating Server TCP listening socket 127.0.0.1:6379: bind: No error解决办法
windows下安装Redis第一次启动报错: [2368] 21 Apr 02:57:05.611 # Creating Server TCP listening socket 127.0.0.1: ...
- RabbitMQ学习之Flow Control
当RabbitMQ发布消息速度快于消费速度或者系统资源不足时,RabbitMQ将降低或阻断发布消息速度,以免服务器资源饱满而宕机,可以通过rabbitmqctl和web管理页面查看连接的状态为flow ...
- html IMG 标签水平居中 ,和图片过大 溢出处理
max-width: 100%;//父元素的宽度 display: block; margin: 0 auto; display: table-cell; 垂直居中 vertical-align: m ...
- VMware ESXi定制版(OEM ISO)资源下载
一.VMware ESXi 5.1.0 update03 链接: https://pan.baidu.com/s/1nvQ4CGD 密码: acc1 1.VMware-ESXi-5.1.0-Updat ...
- Linux搭建oracle数据库
1.安装前准备 软件硬件要求 操作系统:CentOS 6.4(32bit)Oracle数据库版本:Oracle 10g(10201_database_linux32.zip)最小内存:1G(检查命 ...
- UNIX时间转换ASP代码.txt
'参数:strTime:要转换的时 间:intTimeZone:该时间对应的时区 '返回值:strTime相对于1970年1月1日午夜0点经过的秒数 '示例:ToUnixTime("2008 ...
- class一些内置方法
一. __getattribute__ class Foo: def __init__(self,x): self.x=x def __getattr__(self, item): print('执行 ...