UICollectionView 05 - 可伸缩Header

文章按照顺序写的,之前文章写过的很多逻辑都会略过,建议顺序阅读,并下载源码结合阅读。

目录

项目下载地址: CollectionView-Note

UICollectionView 01 - 基础布局篇
UICollectionView 02 - 布局和代理篇
UICollectionView 03 - 自定义布局原理篇
UICollectionView 04 - 卡片布局
UICollectionView 05 - 可伸缩Header
UICollectionView 06 - 瀑布流布局
UICollectionView 07 - 标签布局

上一篇 通过 UICollectionViewFlowLayout ,然后对其cell实时监控根据距离中心位置进行缩放实现了卡片布局 , 这篇继续继承 UICollectionViewFlowLayout 对其SupplementaryView 做一些小处理 ,即可实现可伸缩头部。

继续在 Storyboard 中拖出一个 ViewController , 然后放上一个 UICollectionView . 依旧使用之前篇幅的色块作为cell,这里就放几个横条cell (不关键,本篇主要针对 SupplementaryView)。 然后新建一个继承自UICollectionReusableViewImageHeaderView . 这边使用xib创建的 也可以直接再 Storyboard中或者纯代码 。 ImageView 是靠四个边的。

class ImageHeaderView: UICollectionReusableView {
  
  static let reuseID = "ImageHeaderView"
  
  @IBOutlet weak var imageView: UIImageView!
  
  override func awakeFromNib() {
    super.awakeFromNib()
    imageView.contentMode = .scaleAspectFill
    imageView.clipsToBounds = true
  }
  
}

整个 ViewController 大概就这样


class StretchyHeaderViewController: UIViewController {
  
  @IBOutlet weak var collectionView: UICollectionView!
  
  var layout: UICollectionViewFlowLayout? {
    return collectionView.collectionViewLayout as? UICollectionViewFlowLayout
  }
  
  var colors: [UIColor] = []
  override func viewDidLoad() {
    super.viewDidLoad()
    
    colors = DataManager.shared.generalColors(3)
    collectionView.dataSource = self
    collectionView.register(UINib(nibName: "ImageHeaderView", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: ImageHeaderView.reuseID)
    
    collectionView.register(UINib(nibName: "BasicsHeaderView", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: BasicsHeaderView.reuseID)
    
    collectionView.alwaysBounceVertical = true
    let width = view.bounds.width
    layout?.itemSize = CGSize(width: width, height: 50)
    layout?.minimumLineSpacing = 2
    layout?.headerReferenceSize = CGSize(width: width, height: 150)
  }
  
}


// MARK: - UICollectionViewDataSource

extension StretchyHeaderViewController: UICollectionViewDataSource {
  
  func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return colors.count
  }
  
  func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: BasicsCell.reuseID, for: indexPath) as! BasicsCell
    cell.backgroundColor = colors[indexPath.row]
    return cell
  }
  
  func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
    switch kind {
    case UICollectionView.elementKindSectionHeader:
      let view = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: ImageHeaderView.reuseID, for: indexPath) as! ImageHeaderView
      return view
    default:
      fatalError("No such kind")
    }
  }
  
}

一个很普通的header + cell的布局, 如下,拖动的时候没有任何效果。

000

下面我们自定义一个继承自 UICollectionViewFlowLayoutStretchyLayout .

跟上篇一样重写override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? 方法。

override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
    // 1
    guard let collectionView = self.collectionView else { return nil }
    guard let attributes = super.layoutAttributesForElements(in: rect) else { return nil }

    // 2
    let insets = collectionView.contentInset
    let offset = collectionView.contentOffset
    let minY = -insets.top
    
    // 3
    if offset.y < minY {
      // 4
      let headerSize = self.headerReferenceSize
      let deltalY = abs(offset.y - minY)
      for attibute in attributes {
        // 5 
        if attibute.representedElementKind == UICollectionView.elementKindSectionHeader {
          // 6 
          var headerRect = attibute.frame
          headerRect.size.height = headerSize.height + deltalY
          headerRect.origin.y = headerRect.origin.y - deltalY
          attibute.frame = headerRect
        }
      }
    }
    return attributes
  }

这里解释下

  1. 获取collectionView 和 父类返回的 attributes
  2. 我们的拉伸是从顶部开始拉伸,所以这里获取到当前的 offset 和顶部的 inset
  3. 如果滚动的y坐标比顶部最小的inset还小,就需要拉伸了
  4. 获取到headersize,以及我们滚动超过顶部的距离 deltalY
  5. 遍历 attributes ,我们只针对Section Header 进行处理
  6. 获取到header的frame,根据滚动的距离 ,调整header的大小和坐标。

最后 跟上一篇一样,当bounds改变时重新计算。

override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
    return true
}

ok,其实没啥复杂的东西,然后再storyboard中将layout设置为我们自定义的layout (不会设置的看上一篇)。 ViewController 中获取到的也是我们的 StretchyLayout

var layout: StretchyLayout? {
    return collectionView.collectionViewLayout as? StretchyLayout
}

再次运行。


000
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,233评论 6 495
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,357评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,831评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,313评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,417评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,470评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,482评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,265评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,708评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,997评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,176评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,827评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,503评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,150评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,391评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,034评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,063评论 2 352

推荐阅读更多精彩内容

  • 1、通过CocoaPods安装项目名称项目信息 AFNetworking网络请求组件 FMDB本地数据库组件 SD...
    阳明先生_X自主阅读 15,975评论 3 119
  • 君子兰近来读到汪曾祺的《滇游新记》,里面有定市花的情节,不由想起了老家的几盆君子兰——长春市市花。在吉林省,但凡家...
    高卢的林川迪斯阅读 379评论 0 0
  • —余倩 夜幕降临,进入大二的我结束了一天的课程,洗去了一身的疲倦进去了梦乡…… 梦里一位十六七岁的花季女孩,穿着朴...
    365读书计划阅读 335评论 0 2
  • 我陈庚下定决心,公众承诺,必须彻底改变,让我的生命从此再也不一样。我知道,所有的新结果,来自新的习惯建立,因此,我...
    陈庚新生阅读 182评论 0 0