我正在参加「启航方案」

作用图

iOS设置UICollectionView的Section的背景色和背景图

最近遇到这样一个类似于支付宝运用中心功能模块,UICollectionView点击增删、拖拽、排序功能。看作用点这儿

先不提其他的,这儿出现了UICollectionViewSection设置了背景色??

iOS设置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)

为了更直观增加了区头和区尾,运转后:

iOS设置UICollectionView的Section的背景色和背景图

看图可知:sectionInsetPadding一样,是设置Section内距离而不是外距离。并且也看得出来UICollectionView的默许每个Section都是相邻的,相互之间并没有距离。


思路

据上所述,咱们能够知道UICollectionView的每个Section之间是没有距离的,并且UICollectionView默许是完全没有SectionviewcontentView,或者说压根就没有区的相关UI一说。

没有也没事,没有咱们能够自己造,让SectionDecoration 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的不同特点。

下面一个个完成。 工程文件:

iOS设置UICollectionView的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之间是没有距离的,并且默许咱们增加的每个SectionDecoration view相互之间也是没有距离。这时候能够增加一个 外距离margin 特点,能够设置每个Section的外距离,合作UICollectionViewsectionInset特点来完成咱们想要的作用。

留意一:Decoration是实在的Section区域经过margin内减的得到的。比方实在的Section的宽高为:100×100,设置margin的top、left、bottom、right的值均为10,则核算后Section的Decoration宽高为:80×80。

留意二: 若增加了区头或区尾,一定要留意在区头或区尾增加子控件的尺度,在增加了margin下,显现作用或许出现区头或区尾的子控件方位超出Decoration,这点留意下就行。

headerForSection、footerForSection

由于或许存在区头或区尾,且它们的宽高能够经过headerReferenceSizefooterReferenceSize设置,也能够经过署理来设置,并且或许每个Section存在不同的情况,因而咱们模仿UICollectionViewDelegate,经过署理获取每个区头、区尾的尺度,参加核算Decoration view的尺度。

SectionDecorationLayoutAttributes

这个没什么好说的,UICollectionViewLayoutAttributes是管理指定元素的布局特点的目标,能够运用该目标中的布局特点来控制cell和Supplementary View的方位。

新增imageName、backgroundColor、cornerRadius特点,所界说特点的类型需求遵从 NSCopying 协议。然后重写下 copyisEqual 方法就结束了。

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区域,因而它只受到 contentInsetmargin 的约束,不受 sectionInset 内距离 的影响,只是经过 sectionInset 来核算Decoration view的宽高。

方位核算好后,经过署理获取之前设置的3个特点值,赋值给SectionDecorationLayoutAttributes目标后保存。

水平方向核算方法差不多,只是需求找到Section中X坐标最大的item,遍历下就行。

最终一定要重写 layoutAttributesForDecorationView 方法。

结束

到此,设置UICollectionView的Section的背景色和背景图功能也就完成了,看起来许多,实际上依照步骤一步步完成也不是很难,并且运用起来也很简略,重点是经过 contentInsetsectionInsetmargin 组合设置完成自己需求作用。布局也主张依照这个顺序来设置,能够先设置一个看作用,再考虑是否设置另一个。具体的完成这儿就不展开说了。


代码在下面,有需求的能够自取。

RCSectionDecoration

若存在什么不对的当地,欢迎指正!