UICollectionView 的研究之二 :自定义 UICollectionViewFlowLayout

本文主要是介绍UICollectionView 的研究之二 :自定义 UICollectionViewFlowLayout,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

UICollectionView 实现各式复杂布局核心在于 UICollectionViewLayout,需要我们去自定义实现。

通过各种layout 的自定义实现,以及它们之间的切换。可以实现一些酷炫的布局,例如

(图片选自:http://www.cnblogs.com/markstray/p/5822262.html)

Cover Flow 布局

堆叠布局


圆形布局


关于需要重写方法的描述

自定义布局需要重写以下四个方法

(文字描述取自:https://www.cnblogs.com/wangliang2015/p/5388658.html 和 https://www.cnblogs.com/hissia/p/5723629.html):

 - 作用:在这个方法中做一些初始化操作

 - 注意:子类重写prepareLayout,一定要调用[super prepareLayout]

 - (void)prepareLayout;



 - 作用:

 - 这个方法的返回值是个数组

 - 这个数组中存放的都是UICollectionViewLayoutAttributes对象

 - UICollectionViewLayoutAttributes对象决定了cell的排布方式(frame等)

- (nullable NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect;


 - 作用:如果返回YES,那么collectionView显示的范围发生改变时,就会重新刷新布局

 - 一旦重新刷新布局,就会按顺序调用下面的方法:

 - prepareLayout

 - layoutAttributesForElementsInRect:

- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds;

- 作用:返回值决定了collectionView停止滚动时最终的偏移量(contentOffset)

 - 参数:

 - proposedContentOffset:原本情况下,collectionView停止滚动时最终的偏移量

 - velocity:滚动速率,通过这个参数可以了解滚动的方向

-(CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity;


具体实现逻辑

以 Cover Flow 布局的实现为例子进行阐述


进行初始化

- (instancetype)init {if (self = [super init]) {}return self;
}

进行布局,并且 collectionView 显示 rect 改变是进行布局刷新

- (void)prepareLayout {[super prepareLayout];// 水平滚动self.scrollDirection = UICollectionViewScrollDirectionHorizontal;// 决定第一张图片所在的位置CGFloat margin = (self.collectionView.frame.size.width - self.itemSize.width) / 2;self.collectionView.contentInset = UIEdgeInsetsMake(0, margin, 0, margin);
}- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds {return YES;
} // return YES to cause the collection view to requery the layout for geometry information

该方法是进行自定义的核心,在这里写各种算法以达成想要的效果

该例子中,我们要实现的效果是在滑动的过程中,item 逐渐接近中心,会逐步增大,直到显示最大值,之后不断远离中心点,item 逐步缩小。这一效果类似于三角函数中的正、余弦函数。初步锁定这两个函数,而要选择哪一个?

在滑动的过程中,我们可以得到

self.collectionView.contentOffset.x :这是内容最左侧相对于 collectionView 最左侧的偏移值

attributes.center.x :这是当前 item 的水平中心点,该 x 值是从内容的最左侧算起,直到当前 item 的水平中心点的,全部加起来就是该 item 的水平中心 x。


再者,无论是否滑动,都有一个固定值:

self.collectionView.center.x :位于屏幕水平方向的中心不变,大小不变。



那么,以第一个item 进行分析,self.collectionView.contentOffset.x 与 self.collectionView.contentOffset.的差值与屏幕中心 x 相减的绝对值为item 中心与屏幕中心之间的距离

    

              屏幕中心与item 中心相距为0                                 屏幕中心与item 中心相距40

由此,我们选择余弦函数进行计算。

- (nullable NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect {// 闪屏现象解决参考 :https://blog.csdn.net/u013282507/article/details/53103816//扩大控制范围,防止出现闪屏现象rect.size.width = rect.size.width + KScreenWidth;rect.origin.x = rect.origin.x - KScreenWidth/2;// 让父类布局好样式NSArray *arr = [[NSArray alloc] initWithArray:[super layoutAttributesForElementsInRect:rect] copyItems:YES];for (UICollectionViewLayoutAttributes *attributes in arr) {CGFloat scale;
//        scale = 1.0;// collectionView 的 centerXCGFloat centerX = self.collectionView.center.x;CGFloat step = ABS(centerX - (attributes.center.x - self.collectionView.contentOffset.x));NSLog(@"step %@ : attX %@ - offset %@", @(step), @(attributes.center.x), @(self.collectionView.contentOffset.x));scale = fabsf(cosf(step/centerX * M_PI/5));attributes.transform = CGAffineTransformMakeScale(scale, scale);}return arr;
} // return an array layout attributes instances for all the views in the given rect

确保在滚动结束的时候的显示效果,此处确保某一个item 滚动结束时是居中显示的。

- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity {// 保证滚动结束后视图的显示效果// 计算出最终显示的矩形框CGRect rect;rect.origin.y = 0;rect.origin.x = proposedContentOffset.x;rect.size = self.collectionView.frame.size;// 获得 super 已经计算好的布局的属性NSArray *arr = [super layoutAttributesForElementsInRect:rect];// 计算 collectionView 最中心点的 x 值CGFloat centerX = proposedContentOffset.x + self.collectionView.frame.size.width * 0.5;CGFloat minDelta = MAXFLOAT;for (UICollectionViewLayoutAttributes *attrs in arr) {if (ABS(minDelta) > ABS(attrs.center.x - centerX)) {minDelta = attrs.center.x - centerX;}}proposedContentOffset.x += minDelta;return proposedContentOffset;
} // return a point at which to rest after scrolling - for layouts that want snap-to-point scrolling behavior

代码地址:https://download.csdn.net/download/u013410274/10356732

所有的参考链接:

WWDC 2012 Session 笔记 -- 205 Introducing Collection Views

http://www.cnblogs.com/markstray/p/5822262.html

UICollectionViewLayout 继承 UICollectionViewFlowLayout 自定义布局

https://www.cnblogs.com/wangliang2015/p/5388658.html

自定义流水布局(UICollectionViewFlowLayout 的基本使用)

https://www.cnblogs.com/hissia/p/5723629.html

iOS 利用余弦函数实现卡片浏览工具

https://blog.csdn.net/u013282507/article/details/53103816


这篇关于UICollectionView 的研究之二 :自定义 UICollectionViewFlowLayout的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1142496

相关文章

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

自定义类型:结构体(续)

目录 一. 结构体的内存对齐 1.1 为什么存在内存对齐? 1.2 修改默认对齐数 二. 结构体传参 三. 结构体实现位段 一. 结构体的内存对齐 在前面的文章里我们已经讲过一部分的内存对齐的知识,并举出了两个例子,我们再举出两个例子继续说明: struct S3{double a;int b;char c;};int mian(){printf("%zd\n",s

如何编写Linux PCIe设备驱动器 之二

如何编写Linux PCIe设备驱动器 之二 功能(capability)集功能(capability)APIs通过pci_bus_read_config完成功能存取功能APIs参数pos常量值PCI功能结构 PCI功能IDMSI功能电源功率管理功能 功能(capability)集 功能(capability)APIs int pcie_capability_read_wo

Spring 源码解读:自定义实现Bean定义的注册与解析

引言 在Spring框架中,Bean的注册与解析是整个依赖注入流程的核心步骤。通过Bean定义,Spring容器知道如何创建、配置和管理每个Bean实例。本篇文章将通过实现一个简化版的Bean定义注册与解析机制,帮助你理解Spring框架背后的设计逻辑。我们还将对比Spring中的BeanDefinition和BeanDefinitionRegistry,以全面掌握Bean注册和解析的核心原理。

Oracle type (自定义类型的使用)

oracle - type   type定义: oracle中自定义数据类型 oracle中有基本的数据类型,如number,varchar2,date,numeric,float....但有时候我们需要特殊的格式, 如将name定义为(firstname,lastname)的形式,我们想把这个作为一个表的一列看待,这时候就要我们自己定义一个数据类型 格式 :create or repla

一种改进的red5集群方案的应用、基于Red5服务器集群负载均衡调度算法研究

转自: 一种改进的red5集群方案的应用: http://wenku.baidu.com/link?url=jYQ1wNwHVBqJ-5XCYq0PRligp6Y5q6BYXyISUsF56My8DP8dc9CZ4pZvpPz1abxJn8fojMrL0IyfmMHStpvkotqC1RWlRMGnzVL1X4IPOa_  基于Red5服务器集群负载均衡调度算法研究 http://ww

生信圆桌x生信分析平台:助力生物信息学研究的综合工具

介绍 少走弯路,高效分析;了解生信云,访问 【生信圆桌x生信专用云服务器】 : www.tebteb.cc 生物信息学的迅速发展催生了众多生信分析平台,这些平台通过集成各种生物信息学工具和算法,极大地简化了数据处理和分析流程,使研究人员能够更高效地从海量生物数据中提取有价值的信息。这些平台通常具备友好的用户界面和强大的计算能力,支持不同类型的生物数据分析,如基因组、转录组、蛋白质组等。

开题报告中的研究方法设计:AI能帮你做什么?

AIPaperGPT,论文写作神器~ https://www.aipapergpt.com/ 大家都准备开题报告了吗?研究方法部分是不是已经让你头疼到抓狂? 别急,这可是大多数人都会遇到的难题!尤其是研究方法设计这一块,选定性还是定量,怎么搞才能符合老师的要求? 每次到这儿,头脑一片空白。 好消息是,现在AI工具火得一塌糊涂,比如ChatGPT,居然能帮你在研究方法这块儿上出点主意。是不

研究人员在RSA大会上演示利用恶意JPEG图片入侵企业内网

安全研究人员Marcus Murray在正在旧金山举行的RSA大会上公布了一种利用恶意JPEG图片入侵企业网络内部Windows服务器的新方法。  攻击流程及漏洞分析 最近,安全专家兼渗透测试员Marcus Murray发现了一种利用恶意JPEG图片来攻击Windows服务器的新方法,利用该方法还可以在目标网络中进行特权提升。几天前,在旧金山举行的RSA大会上,该Marcus现场展示了攻击流程,

HTML5自定义属性对象Dataset

原文转自HTML5自定义属性对象Dataset简介 一、html5 自定义属性介绍 之前翻译的“你必须知道的28个HTML5特征、窍门和技术”一文中对于HTML5中自定义合法属性data-已经做过些介绍,就是在HTML5中我们可以使用data-前缀设置我们需要的自定义属性,来进行一些数据的存放,例如我们要在一个文字按钮上存放相对应的id: <a href="javascript:" d