-
Notifications
You must be signed in to change notification settings - Fork 167
Expand file tree
/
Copy pathSegementSlideViewController.swift
More file actions
177 lines (148 loc) 路 5.25 KB
/
Copy pathSegementSlideViewController.swift
File metadata and controls
177 lines (148 loc) 路 5.25 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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
//
// SegementSlideViewController.swift
// SegementSlide
//
// Created by Jiar on 2018/12/7.
// Copyright 漏 2018 Jiar. All rights reserved.
//
import UIKit
public enum BouncesType {
case parent
case child
}
open class SegementSlideViewController: UIViewController {
public internal(set) var scrollView: SegementSlideScrollView!
public internal(set) var headerView: SegementSlideHeaderView!
public internal(set) var contentView: SegementSlideContentView!
public internal(set) var switcherView: SegementSlideSwitcherDelegate!
internal var innerHeaderView: UIView?
internal var safeAreaTopConstraint: NSLayoutConstraint?
internal var parentKeyValueObservation: NSKeyValueObservation?
internal var childKeyValueObservations: [String: NSKeyValueObservation] = [:]
internal var innerBouncesType: BouncesType = .parent
internal var canParentViewScroll: Bool = true
internal var canChildViewScroll: Bool = false
internal var lastChildBouncesTranslationY: CGFloat = 0
internal var cachedChildViewControllerIndex: Set<Int> = Set()
open var headerStickyHeight: CGFloat {
let headerHeight = headerView.frame.height.rounded(.up)
if edgesForExtendedLayout.contains(.top) {
return headerHeight - topLayoutLength
} else {
return headerHeight
}
}
public var switcherHeight: CGFloat {
return switcherView.ssDataSource?.height ?? 44
}
public var contentViewHeight: CGFloat {
return view.bounds.height-topLayoutLength-switcherHeight
}
public var currentIndex: Int? {
return switcherView.ssSelectedIndex
}
public var currentSegementSlideContentViewController: SegementSlideContentScrollViewDelegate? {
guard let currentIndex = currentIndex else {
return nil
}
return contentView.dequeueReusableViewController(at: currentIndex)
}
/// you should call `reloadData()` after set this property.
open var defaultSelectedIndex: Int? {
didSet {
switcherView.ssDefaultSelectedIndex = defaultSelectedIndex
contentView.defaultSelectedIndex = defaultSelectedIndex
}
}
open var bouncesType: BouncesType {
return .parent
}
open func segementSlideHeaderView() -> UIView? {
if edgesForExtendedLayout.contains(.top) {
#if DEBUG
assert(false, "must override this variable")
#endif
return nil
} else {
return nil
}
}
open func segementSlideSwitcherView() -> SegementSlideSwitcherDelegate {
#if DEBUG
assert(false, "must override this variable")
#endif
return SegementSlideSwitcherEmptyView()
}
open func segementSlideContentViewController(at index: Int) -> SegementSlideContentScrollViewDelegate? {
#if DEBUG
assert(false, "must override this function")
#endif
return nil
}
open func scrollViewDidScroll(_ scrollView: UIScrollView, isParent: Bool) {
}
open func didSelectContentViewController(at index: Int) {
}
open func setupHeader() {
innerHeaderView = segementSlideHeaderView()
}
open func setupSwitcher() {
}
open func setupContent() {
cachedChildViewControllerIndex.removeAll()
}
open override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
layoutSegementSlideScrollView()
}
open override func viewDidLoad() {
super.viewDidLoad()
setup()
}
/// reload headerView, SwitcherView and ContentView
///
/// you should set `defaultSelectedIndex` before call this method.
/// otherwise, no item will be selected.
/// however, if an item was previously selected, it will be reSelected.
public func reloadData() {
setupBounces()
setupHeader()
setupSwitcher()
setupContent()
contentView.reloadData()
switcherView.reloadData()
layoutSegementSlideScrollView()
}
/// reload headerView
public func reloadHeader() {
setupHeader()
layoutSegementSlideScrollView()
}
/// reload SwitcherView
public func reloadSwitcher() {
setupSwitcher()
switcherView.reloadData()
layoutSegementSlideScrollView()
}
/// reload ContentView
public func reloadContent() {
setupContent()
contentView.reloadData()
}
/// select one item by index
public func selectItem(at index: Int, animated: Bool) {
switcherView.selectItem(at: index, animated: animated)
}
/// reuse the `SegementSlideContentScrollViewDelegate`
public func dequeueReusableViewController(at index: Int) -> SegementSlideContentScrollViewDelegate? {
return contentView.dequeueReusableViewController(at: index)
}
deinit {
parentKeyValueObservation?.invalidate()
cleanUpChildKeyValueObservations()
NotificationCenter.default.removeObserver(self, name: SegementSlideContentView.willCleanUpAllReusableViewControllersNotification, object: nil)
#if DEBUG
debugPrint("\(type(of: self)) deinit")
#endif
}
}