我正在参加「启航方案」
作用图
最近遇到这样一个类似于支付宝运用中心功能模块,UICollectionView
点击增删、拖拽、排序功能。看作用点这儿。
先不提其他的,这儿出现了UICollectionView
的Section
设置了背景色??
虽然有段时间没写iOS了,但是没听说UICollectionView
有设置Section
背景色的特点啊?问了下,本来组员是用UIScrollView
+ UIView
完成的,不雅观观实属不雅观观,有点low low的。笔者就试试用UICollectionView
来完成次功能,盲猜要自界说一大堆东西了。
sectionInset
在此之前咱们要简略了解下这个特点:sectionInset
:设置Section
的 内距离。
简略用代码运转下:
let layout = UICollectionViewFlowLayout()
layout.sectionInset = UIEdgeInsets(top: 10, left: 10, bottom: 50, right: 10)
layout.headerReferenceSize = CGSize(width: kWidth, height: 40)
layout.footerReferenceSize = CGSize(width: kWidth, height: 40)
为了更直观增加了区头和区尾,运转后:
看图可知:sectionInset
与Padding
一样,是设置Section
的内距离而不是外距离。并且也看得出来UICollectionView
的默许每个Section
都是相邻的,相互之间并没有距离。
思路
据上所述,咱们能够知道UICollectionView
的每个Section
之间是没有距离的,并且UICollectionView
默许是完全没有Section
的view
或contentView
,或者说压根就没有区的相关UI
一说。
没有也没事,没有咱们能够自己造,让Section
有Decoration view
,能够让其设置UI
特点。
Section 和 Decoration view ,相当于 Cell 和 contentView 的关系。
这样思路就来了:
-
继承
UICollectionViewLayoutAttributes
自界说布局特点,增加需求的UI
特点,笔者这儿增加了backgroundColor(背景色)、imageName(网路和本地图片,依据hasPrefix("http")
判别)、cornerRadius(圆角)。 -
继承
UICollectionReusableView
,自界说增加一个UIImageView
作为Section
的装修背景图,之所以挑选UIImageView
是由于既能够满足增加背景色也能够增加背景图片。 -
自界说
UICollectionViewFlowLayout
,重写prepare
布局,核算每个Decoration view
的方位,并回来相关的UI
特点。 -
模仿
UICollectionView
的署理,新增一个协议sectionDelegate
,运用署理来设置每个Section
的不同特点。
下面一个个完成。 工程文件:
SectionDecorationFlowLayoutDelegate
是模仿UICollectionView
的署理,新增的署理协议sectionDelegate
,代码:
// 设置Section背景色,默许:white
func collectionView(_ collectionView:UICollectionView,layoutcollectionViewLayout: SectionDecorationFlowLayout,backgroundColorForSectionAt section:Int) -> UIColor
// 设置Section的背景图片,默许:nil(简略判别下:依据是否含http判别是网络图片仍是本地图片)
func collectionView(_ collectionView: UICollectionView,layout collectionViewLayout: SectionDecorationFlowLayout,backgroundImageForSectionAt section: Int) -> String?
// 设置Section背景圆角,默许:nil
func collectionView(_ collectionView: UICollectionView,layout collectionViewLayout: SectionDecorationFlowLayout,cornerRadiusForSectionAt section: Int) -> CGFloat?
// 设置Section背景的外距离,默许:UIEdgeInsets.zero
func collectionView(collectionView: UICollectionView,layout collectionViewLayout: SectionDecorationFlowLayout,marginForSectionAt section: Int) -> UIEdgeInsets
// 设置Section Header 宽高,默许:CGSizeZero
func collectionView(collectionView: UICollectionView,layout collectionViewLayout:SectionDecorationFlowLayout,headerForSectionAt section: Int) -> CGSize
// 设置Section Footer 宽高,默许:CGSizeZero
func collectionView(collectionView: UICollectionView,layout collectionViewLayout:SectionDecorationFlowLayout,footerForSectionAt section: Int) -> CGSize
然后再扩展下,设置每个特点的默许值。 这儿笔者除了增加背景色、背景图片、圆角,还额定设置了3个其他的特点,这3个重点说下。
marginForSection:外距离
由上可知UICollectionView
的每个Section
之间是没有距离的,并且默许咱们增加的每个Section
的Decoration view
相互之间也是没有距离。这时候能够增加一个 外距离margin 特点,能够设置每个Section
的外距离,合作UICollectionView
的sectionInset
特点来完成咱们想要的作用。
留意一:Decoration是实在的Section区域经过margin内减的得到的。比方实在的Section的宽高为:100×100,设置margin的top、left、bottom、right的值均为10,则核算后Section的Decoration宽高为:80×80。
留意二: 若增加了区头或区尾,一定要留意在区头或区尾增加子控件的尺度,在增加了margin下,显现作用或许出现区头或区尾的子控件方位超出Decoration,这点留意下就行。
headerForSection、footerForSection
由于或许存在区头或区尾,且它们的宽高能够经过headerReferenceSize
、footerReferenceSize
设置,也能够经过署理来设置,并且或许每个Section
存在不同的情况,因而咱们模仿UICollectionViewDelegate
,经过署理获取每个区头、区尾的尺度,参加核算Decoration view
的尺度。
SectionDecorationLayoutAttributes
这个没什么好说的,UICollectionViewLayoutAttributes
是管理指定元素的布局特点的目标,能够运用该目标中的布局特点来控制cell和Supplementary View的方位。
新增imageName、backgroundColor、cornerRadius特点,所界说特点的类型需求遵从 NSCopying 协议。然后重写下 copy 和 isEqual 方法就结束了。
SectionDecorationReusableView
在这儿自界说UICollectionReusableView
,新增一个UIImageView
来作为Decoration view
。重写 apply 方法,经过UICollectionViewLayoutAttributes
拿到对应Section的数据,给UIImageView
设置相应的特点。
SectionDecorationFlowLayout
这个是重点了,重写 prepare 方法,核算每个Section的方位。核算方位前需求区别scrollDirection
这儿就以笔直方向为例说明。
// 获取以下数据:
firstItem // 第一个Item
lastItem // 最终一个Itme
margin // 依据署理获取section的外边距
headerSize // 依据署理获取section header的size
footerSize // 依据署理获取section footer的size
collectionInset // collectionView的contentInset
let x = margin.left
let y = firstItem.frame.origin.y - sectionInset.top - collectionInset.top + margin.top - headerSize.height
let w = self.collectionView!.frame.size.width - collectionInset.left - collectionInset.right - margin.left - margin.right
let h = CGRectGetMaxY(lastItem.frame) - firstItem.frame.origin.y + sectionInset.top + sectionInset.bottom + headerSize.height + footerSize.height - margin.top - margin.bottom
decorationFrame = CGRect(x: x, y: y, width: w, height: h)
contentInset 是最大的约束,一切的布局都会受到约束。
Decoration view
默许填充整个实在的Section区域,因而它只受到 contentInset 和 margin 的约束,不受 sectionInset 内距离 的影响,只是经过 sectionInset 来核算Decoration view
的宽高。
方位核算好后,经过署理获取之前设置的3个特点值,赋值给SectionDecorationLayoutAttributes
目标后保存。
水平方向核算方法差不多,只是需求找到Section中X坐标最大的item,遍历下就行。
最终一定要重写 layoutAttributesForDecorationView 方法。
结束
到此,设置UICollectionView的Section的背景色和背景图功能也就完成了,看起来许多,实际上依照步骤一步步完成也不是很难,并且运用起来也很简略,重点是经过 contentInset 、sectionInset、margin 组合设置完成自己需求作用。布局也主张依照这个顺序来设置,能够先设置一个看作用,再考虑是否设置另一个。具体的完成这儿就不展开说了。
代码在下面,有需求的能够自取。
RCSectionDecoration
若存在什么不对的当地,欢迎指正!