钟情圆角怎么办


最近由于我们的UI钟情于圆角搞得我很方,各种圆角渐变,于是就有了下面这篇给UICollection组设置圆角和背景色的诞生,不知道在我们平时有没有遇到这样子的一些需求,就是按照每一组给UIColllectionView设置不同的背景色,要是没有遇到的同学建议可以先思考一下改怎么处理在看下面的内容吧。

首先需要考虑的是在哪里设置了,我们都应该知道关于CollectionView的属性几乎都是在Layout里面在管理的,那我们要给它设置背景色和院圆角也肯定是在在这去写的了,在大小间距等布局方面我们遵循的都是 UICollectionViewDelegateFlowLayout 这个代理,但这时候我们就应该想到这个DelegateFlowLayout里面没有设置背景色和圆角的代理的,我们需要背景色这个概念的话就只能去注册一个修饰View然后给修饰的View去设置背景色和圆角了。

  1. // MARK: - 注册一个装饰View
  2. func registClass() {
  3.  
  4. self.register(PPReusableView.self, forDecorationViewOfKind: PPCollectionViewSectionBackground)
  5. }

      NOTE:  PPReusableView.self 这个语法在OC中就等于[PPReusableView Class]

PPReusableView是继承与UICollectionReusableView这个装饰View,我们后面会说这个View  后面的 PPCollectionViewSectionBackground 就是我们平时像注册cell时候的一个 identify  而已。

重点


在我们写瀑布流或者别的一些布局的时候,我们都是在哪里重写的? 没错就是 prepare 方法, 我把这整个方法全都放出来看,注释写的很仔细的,要是有不理解的地方可以再留言Q我,具体的肯定是我们继承 UICollectionViewFlowLayout 写了,这里需要注意UICollectionViewFlowLayout和UICollectionViewDelegateFlowLayout,别搞混淆了。按照如下定义一个PPBaseFlowLayout继承与UICollectionViewFlowLayout,在里面我们重写prepare这个方法。

  1. // MARK: - 重写 - prepare
  2. // NOTE: 该方法会在你每次刷新collection data 的时候都会调用
  3. override func prepare() {
  4. super.prepare()
  5.  
  6. self.layoutAttributes?.removeAll()
  7. /// 有多少组
  8. let numberOfSections = self.collectionView?.numberOfSections ?? 0
  9. let delegate = self.collectionView?.delegate
  10. /// 不存在就直接返回 没法再往下设置
  11. guard (numberOfSections != 0) || !(delegate is PPCollectionViewDelegateFlowLayout) else {
  12. return
  13. }
  14. // 循环遍历各组 设置添加的属性
  15. for section in 0..<numberOfSections {
  16.  
  17. /// 一组的Item
  18. let numberOfItems = self.collectionView?.numberOfItems(inSection: section)
  19. if (numberOfItems! <= 0) {
  20. continue;
  21. }
  22.  
  23. /// 每一组第一个item的Attributes
  24. let firstItem = self.layoutAttributesForItem(at: IndexPath.init(item: 0, section: section))
  25. /// 每一组最后一个item的Attributes
  26. let lastItem = self.layoutAttributesForItem(at: IndexPath.init(item: numberOfItems! - 1, section: section))
  27. /// 满足条件 结束本次循环执行下一次
  28. if ((firstItem == nil) || (lastItem == nil)) {
  29. continue
  30. }
  31. if(delegate?.responds(to:#selector(UICollectionViewDelegateFlowLayout.collectionView(_:layout:insetForSectionAt:))))! {
  32.  
  33. let inset = (delegate as? UICollectionViewDelegateFlowLayout)? .collectionView?(self.collectionView!, layout: self, insetForSectionAt: section)
  34. self.sectionInset = inset!
  35. }
  36.  
  37. /// 获取第一个和最后一个item的联合frame ,得到的就是这一组的frame
  38. var sectionFrame:CGRect = firstItem!.frame.union(lastItem!.frame)
  39. /// 设置它的x.y
  40. sectionFrame.origin.x -= self.sectionInset.left - 10
  41. sectionFrame.origin.y -= self.sectionInset.top
  42. ///横向滚动
  43. if self.scrollDirection == .horizontal{
  44.  
  45. /// 计算组的宽的时候要把缩进进去的距离加回来 因为缩进是内容缩进
  46. sectionFrame.size.width += self.sectionInset.left + self.sectionInset.right
  47. /// 横向滚动的时候 组的高就是collectionView的高
  48. sectionFrame.size.height = self.collectionView!.frame.size.height
  49. /// 纵向滚动
  50. }else{
  51. /// 纵向滚动的时候组的宽度
  52. sectionFrame.size.width = self.collectionView!.frame.size.width-20
  53. sectionFrame.size.height += self.sectionInset.top + self.sectionInset.bottom
  54. }
  55. /// 根据自定义的PPCollectionViewSectionBackground 装饰View初始化一个自定义的PPLayoutAttributes
  56. let attribute = PPLayoutAttributes.init(forDecorationViewOfKind:PPCollectionViewSectionBackground,with: IndexPath.init(item: 0, section: section))
  57.  
  58. attribute.frame = sectionFrame
  59. attribute.zIndex = -1
  60. /// 背景色
  61. attribute.backgroundColor = (delegate as? PPCollectionViewDelegateFlowLayout)?.backgroundColorForSection!(collectionView: self.collectionView!, layout: self, section: section)
  62. /// 圆角
  63. attribute.corners = (delegate as? PPCollectionViewDelegateFlowLayout)?.sessionBackgroundViewCornerscollectionView!(collectionView: self.collectionView!, layout: self, section: section)
  64. self.layoutAttributes?.append(attribute)
  65. }
  66. }

NOTE:仔细看代码可以看到圆角和背景色的属性都是设置给PPLayoutAttributes,这玩意又是什么呢?就是我们CollectionView的属性管理者UICollectionViewLayoutAttributes,你进UICollectionViewLayoutAttributes可以看到它的属性有那些,不要忘记我们是根据修饰View初始化得到这个属性的,按照正常的操作我们会在最后返回一个属性数组,自定义过collection布局的应该清楚一些,具体的PPCollectionViewDelegateFlowLayout就是我们继承与UICollectionViewDelegateFlowLayout写的代理了,这个代理里面也就两个方法,圆角和颜色的设置,代码如下:

  1. // MARK: - 可以在协议里面添加代理方法用于设置你想给CollectionView添加的属性设置值
  2. @objc protocol PPCollectionViewDelegateFlowLayout:UICollectionViewDelegateFlowLayout{
  3.  
  4. /// 给CollectionView 的组设置背景颜色
  5. ///
  6. /// - Parameters:
  7. /// - collectionView: collectionView description
  8. /// - layout: layout description
  9. /// - section: section description
  10. /// - Returns: return value description
  11. @objc optional func backgroundColorForSection(collectionView:UICollectionView,
  12. layout:UICollectionViewLayout,
  13. section:NSInteger) -> UIColor
  14.  
  15. /// 给CollectionView 的组设置圆角
  16. ///
  17. /// - Parameters:
  18. /// - collectionView: collectionView description
  19. /// - layout: layout description
  20. /// - section: section description
  21. /// - Returns: UIRectCorner eg:[.topLeft,.topRight]
  22. @objc optional func sessionBackgroundViewCornerscollectionView(collectionView:UICollectionView,
  23. layout:UICollectionViewLayout,
  24. section:NSInteger) -> UIRectCorner
  25. }

说说这个PPLayoutAttributes吧


这个还真没法仔细说,因为....... 下面就是它的全部代码

  1. import Foundation
  2. import UIKit
  3.  
  4. // MARK: - 这里可以给CollectionView 添加自定义属性
  5. class PPLayoutAttributes: UICollectionViewLayoutAttributes {
  6.  
  7. var backgroundColor:UIColor?
  8. var corners:UIRectCorner?
  9. }

不能忘记了PPReusableView,它的代码也比较的简单,如下

  1. import Foundation
  2. import UIKit
  3.  
  4. // MARK: - 可重复使用视图
  5. class PPReusableView: UICollectionReusableView {
  6.  
  7. override func apply(_ layoutAttributes: UICollectionViewLayoutAttributes) {
  8. super.apply(layoutAttributes)
  9.  
  10. if layoutAttributes.isKind(of: PPLayoutAttributes.self) {
  11.  
  12. let layoutAttribute = layoutAttributes as? PPLayoutAttributes
  13. if layoutAttribute!.backgroundColor != nil {
  14. self.backgroundColor = layoutAttribute!.backgroundColor
  15. }
  16. /// 默认设置为 12 以后有需要可以自定义
  17. if layoutAttribute!.corners != nil {
  18. self.setRoundingCorners(layoutAttribute!.corners!, cornerRadii: kDefaultCornerRadii)
  19. }
  20. }
  21. }
  22. }

可以了返回你的属性吧


随后就是返回你前面设置了那么多的属性,具体的就是下面的代码所示了

  1. // MARK: - 重写 - layoutAttributesForElements 返回各组的属性
  2. override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
  3.  
  4. var attributes = super.layoutAttributesForElements(in: rect)
  5. ///
  6. for attribute in self.layoutAttributes! {
  7.  
  8. ///判断两个区域是否相交
  9. if rect.intersects(attribute.frame){
  10.  
  11. attributes?.append(attribute)
  12. }
  13. }
  14. return attributes
  15. }
  16.  
  17. // MARK: - 重写 - layoutAttributesForDecorationView 给装饰的View返回属性
  18. /// Decorationview 装饰view
  19. override func layoutAttributesForDecorationView(ofKind elementKind: String, at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
  20.  
  21. if elementKind == PPCollectionViewSectionBackground {
  22.  
  23. return self.layoutAttributes![indexPath.section]
  24. }
  25. return super.layoutAttributesForDecorationView(ofKind: elementKind, at: indexPath)
  26. }

最后:

最后我们在最前面说的registClass这个方法我们在PPBaseFlowLayout的初始化方法里面调用就可以了,还有属性数组这写就不用说了吧还是在前面自己定义初始化了。

然后上面代码里面的一些宏定义比如identify还有圆角大小等等这些就根据自己的需求去写吧。

最后在初始化CollectionView的时候layout就是我们定义的PPBaseFlowLayout了,遵守的代理就是PPCollectionViewDelegateFlowLayout,这个需要留意下就OK。

Swift - 给UICollectionview设置组背景和圆角的更多相关文章

  1. Android给TextView设置透明背景、圆角边框

    第一种方法:在drawable文件夹下新建一个文件设置背景样式 代码: 在drawable文件夹下面新建text_view_border.xml <?xml version="1.0& ...

  2. Swift开发教程--设置UIViewController的背景透明

    非常easy的一句代码 self.view.backgroundColor = UIColor.clearColor() 由此联想开来,非常多的控件想设置为背景透明都能够用UIColor.clearC ...

  3. Qt 之 设置窗口边框的圆角(使用QSS和PaintEvent两种方法)

    Qt在设置窗口边框圆角时有两种方式,一种是设置样式,另一种是在paintEvent事件中绘制窗口.下面分别叙述用这两种方式来实现窗口边框圆角的效果. 一.使用setStyleSheet方法 this- ...

  4. iOS 11 导航栏 item 偏移问题 和 Swift 下 UIButton 设置 title、image 显示问题

    html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,bi ...

  5. APUE学习之三个特殊位 设置用户ID(set-user-ID),设置组ID(set-group-ID),sticky

    设置用户ID(set-user-ID),设置组ID(set-group-ID),sticky   set-user-ID: SUID      当文件的该位有设置时,表示当该文件被执行时,程序具有文件 ...

  6. 【转】linux 设置用户id 设置组id

    linux 设置用户id 设置组id   转自 linux 设置用户id 设置组id   最近看apue,简单记录对设置用户id理解(设置组id同理). 1. 相关的id好像很多,共有哪些? 文件2个 ...

  7. Windows 7个性化配置,关闭Win7动画效果,设置窗口背景为“ 豆绿色”

    减少眼睛疲劳配色(豆绿色): RGB:, , ,颜色名称:#C7EDCC 1.任务栏设置 2.关闭Win7动画效果 控制面板 -> 轻松访问 -> 优化视频显示 3.去掉窗口阴影 右键单击 ...

  8. 在IE6下使用filter设置png背景

    今天帮别人解决问题学会了一个在IE6下使用filter设置png背景,具体css写法如下: .login_form_wrap { width: 778px; height: 360px; backgr ...

  9. 导航栏视图设置 tabbleView 是设置总背景图

    //导航栏视图设置 tabbleView 是设置总背景图 //默认的时白色半透明(有点灰的感觉), UIBarStyleBlack,UIBarStyleBlackTranslucent ,UIBarS ...

随机推荐

  1. MybatisPlus3.X使用配置

    本文讲解了MyBatis-Plus在使用过程中的配置选项,其中,部分配置继承自MyBatis原生所支持的配置 基本配置 本部分配置包含了大部分用户的常用配置,其中一部分为 MyBatis 原生所支持的 ...

  2. DB2中的MQT优化机制详解和实践

    MQT :物化查询表.是以一次查询的结果为基础  定义创建的表(实表),以量取胜(特别是在百万,千万级别的量,效果更显著),可以更快的查询到我们需要的结果.MQT有两种类型,一种是系统维护的MQT , ...

  3. 一次flume exec source采集日志到kafka因为单条日志数据非常大同步失败的踩坑带来的思考

    本次遇到的问题描述,日志采集同步时,当单条日志(日志文件中一行日志)超过2M大小,数据无法采集同步到kafka,分析后,共踩到如下几个坑.1.flume采集时,通过shell+EXEC(tail -F ...

  4. Java创建线程的四种方式

    Java创建线程的四种方式 1.继承Thread类创建线程 定义Thread类的子类,并重写该类的run方法,run()方法的内容就是该线程执行的内容 创建Thread子类的实例,即创建了线程对象. ...

  5. ssh WARNING:REMOTE HOST IDENTIFICATION HAS CHANGED(警告:远程主机标识已更改)

    ssh 192.168.1.88 出现以下警告: @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ WARNING: REMOT ...

  6. 水管局长数据加强版:lct,时光倒流,最小生成树,边化点

    Description: SC省MY市有着庞大的地下水管网络,嘟嘟是MY市的水管局长(就是管水管的啦),嘟嘟作为水管局长的工作就是:每天供水公司可能要将一定量的水从x处送往y处,嘟嘟需要为供水公司找到 ...

  7. Apache配置反向代理、负载均衡和集群(mod_proxy方式)

    Apache配置负载均衡和集群使用mod_jk的方式比较多,但是mod_jk已经停止更新,并且配置相对复杂.Apache2.2以后,提供了一种原生的方式配置负载均衡和集群,比mod_jk简单很多. 1 ...

  8. Project Euler 52: Permuted multiples

    可以看到数字125874的两倍251748和它有着完全相同的数字,只是顺序不同而已.求一个最小的正整数\(x\),使得\(2x,3x,4x,5x,6x\)都有完全相同的数字. 分析:此题的思路比较直接 ...

  9. NOIP 模拟29 B 侥幸

    这次考得好纯属是侥幸,我T3打表试数试了两个小时,没有想打T2的正解(其实是打不出来)所以这个T3A掉纯属是侥幸,以后还是要打正解 (以下博客最好按全选观看,鬼知道为啥这个样子!) 在这里也口胡一下我 ...

  10. 关于数论分块里r=sum/(sum/l)的证明!

    今天的模拟赛里T2要使用到数论分块,里面有一个重要的坎就是关于r=sum/(sum/l)的证明,网上关于这道题的题解里都没有关于这个的证明,那么我就来填补一下: 在以下的文章里,我都会使用lo(x)表 ...