-
Notifications
You must be signed in to change notification settings - Fork 265
Expand file tree
/
Copy pathStickyLayout.swift
More file actions
65 lines (57 loc) · 2.06 KB
/
StickyLayout.swift
File metadata and controls
65 lines (57 loc) · 2.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
//
// StickyLayout.swift
// CollectionKit
//
// Created by Luke Zhao on 2017-08-31.
// Copyright © 2017 lkzhao. All rights reserved.
//
import UIKit
public class StickyLayout: WrapperLayout {
public var isStickyFn: (Int) -> Bool
var stickyFrames: [(index: Int, frame: CGRect)] = []
var visibleFrame: CGRect = .zero
var topFrameIndex: Int = 0
public init(rootLayout: Layout,
isStickyFn: @escaping (Int) -> Bool = { $0 % 2 == 0 }) {
self.isStickyFn = isStickyFn
super.init(rootLayout)
}
public override var contentSize: CGSize {
return rootLayout.contentSize
}
public override func layout(context: LayoutContext) {
rootLayout.layout(context: context)
stickyFrames = (0..<context.numberOfItems).filter {
isStickyFn($0)
}.map {
(index: $0, frame: rootLayout.frame(at: $0))
}
}
// TODO: Fix for the new FlattenedProvider.visible(in:)
public override func visible(in visibleFrame: CGRect) -> (indexes: [Int], frame: CGRect) {
self.visibleFrame = visibleFrame
topFrameIndex = stickyFrames.binarySearch { $0.frame.minY < visibleFrame.minY } - 1
if let index = stickyFrames.get(topFrameIndex)?.index, index >= 0 {
var oldVisible = rootLayout.visible(in: visibleFrame)
if let index = oldVisible.indexes.index(of: index) {
oldVisible.indexes.remove(at: index)
}
oldVisible.indexes += [index]
return oldVisible
}
return rootLayout.visible(in: visibleFrame)
}
public override func frame(at: Int) -> CGRect {
let superFrame = rootLayout.frame(at: at)
if superFrame.minY < visibleFrame.minY, let index = stickyFrames.get(topFrameIndex)?.index, index == at {
let pushedY: CGFloat
if topFrameIndex < stickyFrames.count - 1 {
pushedY = rootLayout.frame(at: stickyFrames[topFrameIndex + 1].index).minY - superFrame.height
} else {
pushedY = visibleFrame.maxY - superFrame.height
}
return CGRect(origin: CGPoint(x: superFrame.minX, y: min(visibleFrame.minY, pushedY)), size: superFrame.size)
}
return superFrame
}
}