@@ -181,6 +181,7 @@ |
||
181 | 181 |
0543E80F21D1FD1100A42807 /* GroupDetailItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0543E80E21D1FD1100A42807 /* GroupDetailItem.swift */; }; |
182 | 182 |
0546D9852242460700742939 /* OriginData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0546D9842242460700742939 /* OriginData.swift */; }; |
183 | 183 |
054B6C45223F884600939FE6 /* PhotoDetailRemoteAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 054B6C44223F884600939FE6 /* PhotoDetailRemoteAPI.swift */; }; |
184 |
+ 054D8398228288FD0074561A /* NavigationBarConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 054D8397228288FD0074561A /* NavigationBarConfiguration.swift */; }; |
|
184 | 185 |
05594BFF2240BEDE002D4910 /* PhotoDetailViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05594BFE2240BEDE002D4910 /* PhotoDetailViewModel.swift */; }; |
185 | 186 |
05594C012240BF9C002D4910 /* PhotoPurchaseViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05594C002240BF9C002D4910 /* PhotoPurchaseViewModel.swift */; }; |
186 | 187 |
05594C032240E94E002D4910 /* PhotoDetailImageCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05594C022240E94E002D4910 /* PhotoDetailImageCell.swift */; }; |
@@ -436,6 +437,7 @@ |
||
436 | 437 |
054863661FA326CB00A39DA0 /* PhotoCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhotoCell.swift; sourceTree = "<group>"; }; |
437 | 438 |
054863671FA326CB00A39DA0 /* PhotoCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = PhotoCell.xib; sourceTree = "<group>"; }; |
438 | 439 |
054B6C44223F884600939FE6 /* PhotoDetailRemoteAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoDetailRemoteAPI.swift; sourceTree = "<group>"; }; |
440 |
+ 054D8397228288FD0074561A /* NavigationBarConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationBarConfiguration.swift; sourceTree = "<group>"; }; |
|
439 | 441 |
05594BFE2240BEDE002D4910 /* PhotoDetailViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoDetailViewModel.swift; sourceTree = "<group>"; }; |
440 | 442 |
05594C002240BF9C002D4910 /* PhotoPurchaseViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoPurchaseViewModel.swift; sourceTree = "<group>"; }; |
441 | 443 |
05594C022240E94E002D4910 /* PhotoDetailImageCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoDetailImageCell.swift; sourceTree = "<group>"; }; |
@@ -642,6 +644,7 @@ |
||
642 | 644 |
children = ( |
643 | 645 |
05AF61BE226EFAF700AD8E2F /* NavigationBar.swift */, |
644 | 646 |
05EE558A226F070B00E13460 /* NavigationController.swift */, |
647 |
+ 054D8397228288FD0074561A /* NavigationBarConfiguration.swift */, |
|
645 | 648 |
); |
646 | 649 |
path = NavigationController; |
647 | 650 |
sourceTree = "<group>"; |
@@ -1595,7 +1598,7 @@ |
||
1595 | 1598 |
); |
1596 | 1599 |
runOnlyForDeploymentPostprocessing = 0; |
1597 | 1600 |
shellPath = /bin/sh; |
1598 |
- shellScript = "/usr/local/bin/carthage copy-frameworks\nif which swiftlint >/dev/null; then\nswiftlint\nelse\necho \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n"; |
|
1601 |
+ shellScript = "/usr/local/bin/carthage copy-frameworks\n"; |
|
1599 | 1602 |
}; |
1600 | 1603 |
/* End PBXShellScriptBuildPhase section */ |
1601 | 1604 |
|
@@ -1652,6 +1655,7 @@ |
||
1652 | 1655 |
05130F5A21C94C12004EF1BE /* PresentDisappearAnimatedTransitioning.swift in Sources */, |
1653 | 1656 |
053E126721F1719F00A64893 /* PageItem.swift in Sources */, |
1654 | 1657 |
053E127821F5B6E400A64893 /* AlertController.swift in Sources */, |
1658 |
+ 054D8398228288FD0074561A /* NavigationBarConfiguration.swift in Sources */, |
|
1655 | 1659 |
05C5285621FE98F50090ECB5 /* GestureRecognizerProxy.swift in Sources */, |
1656 | 1660 |
05130F5921C94C12004EF1BE /* AlertViewController.swift in Sources */, |
1657 | 1661 |
05EE558B226F070B00E13460 /* NavigationController.swift in Sources */, |
@@ -22,9 +22,17 @@ public extension UIImage { |
||
22 | 22 |
let renderer = UIGraphicsImageRenderer(size: outputSize) |
23 | 23 |
return renderer.jpegData(withCompressionQuality: quality) { _ in |
24 | 24 |
let content = UIGraphicsGetCurrentContext() |
25 |
- content?.draw(cgImage!, in: CGRect.init(origin: CGPoint.zero, size: outputSize)) |
|
25 |
+ content?.draw(cgImage!, in: CGRect(origin: CGPoint.zero, size: outputSize)) |
|
26 | 26 |
} |
27 | 27 |
} |
28 |
+ |
|
29 |
+ func combineTo(image: UIImage, proportion: CGFloat, size: CGSize) { |
|
30 |
+ let renderer = UIGraphicsImageRenderer(size: size) |
|
31 |
+ renderer.image(actions: { context in |
|
32 |
+ context.currentImage.draw(in: CGRect.init(x: 0, y: 0, width: size.width * proportion, height: size.height)) |
|
33 |
+ image.draw(in: CGRect.init(x: size.width * proportion, y: 0, width: size.width * (1 - proportion), height: size.height)) |
|
34 |
+ }) |
|
35 |
+ } |
|
28 | 36 |
} |
29 | 37 |
|
30 | 38 |
public extension UIImage { |
@@ -9,52 +9,7 @@ |
||
9 | 9 |
import UIKit |
10 | 10 |
|
11 | 11 |
class NavigationBar: UINavigationBar { |
12 |
- |
|
13 |
- private var currBgImage: UIImage? |
|
14 |
- private var targetBgImage: UIImage? |
|
15 |
- private var originShadowImage: UIImage? |
|
16 |
- |
|
17 |
- private var hasChangedBgImage: Bool = false |
|
18 |
- private var hasChangedShadow: Bool = false |
|
19 |
- private var titleView: UIView? |
|
20 |
- |
|
21 |
- var needsInteractive: Bool { |
|
22 |
- return hasChangedBgImage || hasChangedShadow |
|
23 |
- } |
|
24 |
- var bounce: Bounce = .none |
|
25 |
- var isPush: Bool = true |
|
26 |
- |
|
27 |
- override var shadowImage: UIImage? { |
|
28 |
- didSet { |
|
29 |
- originShadowImage = oldValue |
|
30 |
- hasChangedShadow = true |
|
31 |
- } |
|
32 |
- } |
|
33 |
- |
|
34 |
- lazy var fakeView: UIVisualEffectView = { |
|
35 |
- let val = UIVisualEffectView(effect: UIBlurEffect(style: .light)) |
|
36 |
- val.frame = getNavigationBarBounds() |
|
37 |
- val.isUserInteractionEnabled = false |
|
38 |
- val.autoresizingMask = [.flexibleWidth, .flexibleHeight] |
|
39 |
- |
|
40 |
- return val |
|
41 |
- }() |
|
42 |
- |
|
43 |
- lazy var backgroundImageView: UIImageView = { |
|
44 |
- let view = UIImageView() |
|
45 |
- view.isUserInteractionEnabled = false |
|
46 |
- view.frame = getNavigationBarBounds().offsetBy(dx: bounds.width, dy: 0) |
|
47 |
- |
|
48 |
- return view |
|
49 |
- }() |
|
50 |
- |
|
51 |
- lazy var shadowImageView: UIImageView = { |
|
52 |
- let view = UIImageView() |
|
53 |
- view.frame = CGRect(x: 0, y: bounds.height, width: bounds.width, height: 0.5) |
|
54 |
- |
|
55 |
- return view |
|
56 |
- }() |
|
57 |
- |
|
12 |
+ |
|
58 | 13 |
override init(frame: CGRect) { |
59 | 14 |
super.init(frame: frame) |
60 | 15 |
} |
@@ -62,170 +17,86 @@ class NavigationBar: UINavigationBar { |
||
62 | 17 |
required init?(coder aDecoder: NSCoder) { |
63 | 18 |
fatalError("init(coder:) has not been implemented") |
64 | 19 |
} |
65 |
- override func setBackgroundImage(_ backgroundImage: UIImage?, for barMetrics: UIBarMetrics) { |
|
66 |
- currBgImage = self.backgroundImage(for: .default) |
|
67 |
- targetBgImage = backgroundImage |
|
68 |
- hasChangedBgImage = true |
|
69 |
- } |
|
70 | 20 |
|
71 |
- override func setBackgroundImage(_ backgroundImage: UIImage?, |
|
72 |
- for barPosition: UIBarPosition, |
|
73 |
- barMetrics: UIBarMetrics) { |
|
74 |
- currBgImage = self.backgroundImage(for: .default) |
|
75 |
- targetBgImage = backgroundImage |
|
76 |
- hasChangedBgImage = true |
|
21 |
+ func getNavigationBarBounds() -> CGRect { |
|
22 |
+ let statusHeight = UIApplication.shared.statusBarFrame.height |
|
23 |
+ return CGRect(x: 0, y: -statusHeight, width: bounds.width, height: bounds.height + statusHeight) |
|
77 | 24 |
} |
78 | 25 |
|
79 |
- func setBackgroundImage() { |
|
80 |
- super.setBackgroundImage(targetBgImage, for: .any, barMetrics: .default) |
|
26 |
+ override func value(forUndefinedKey key: String) -> Any? { |
|
27 |
+ return nil |
|
81 | 28 |
} |
29 |
+} |
|
82 | 30 |
|
31 |
+public extension UINavigationBar { |
|
83 | 32 |
func getBarBackground() -> UIView? { |
84 |
- return value(forKeyPath: "_backgroundView") as? UIView |
|
33 |
+ return value(forKeyPath: "_backgroundView") as? UIView |
|
85 | 34 |
} |
86 |
- |
|
87 |
- func getContentView() -> UIView? { |
|
35 |
+ |
|
36 |
+ func getBarContentView() -> UIView? { |
|
88 | 37 |
for val in subviews { |
89 |
- if let contentClass = NSClassFromString("_UINavigationBarContentView"), val.isKind(of: contentClass) { |
|
38 |
+ if let contentClass = NSClassFromString("_UINavigationBarContentView"), |
|
39 |
+ val.isKind(of: contentClass) { |
|
90 | 40 |
return val |
91 | 41 |
} |
92 | 42 |
} |
93 | 43 |
return nil |
94 | 44 |
} |
95 |
- |
|
45 |
+ |
|
96 | 46 |
func getShadowView() -> UIView? { |
97 | 47 |
guard let barBackground = getBarBackground() else { return nil } |
98 |
- for val in barBackground.subviews where val.bounds.height == 0.5 { |
|
99 |
- return val |
|
48 |
+ for view in barBackground.subviews where view.bounds.height == 0.5 { |
|
49 |
+ return view |
|
100 | 50 |
} |
101 | 51 |
return nil |
102 | 52 |
} |
103 |
- |
|
104 |
- func getNavigationBarBounds() -> CGRect { |
|
105 |
- let statusHeight = UIApplication.shared.statusBarFrame.height |
|
106 |
- return CGRect(x: 0, y: -statusHeight, width: bounds.width, height: bounds.height + statusHeight) |
|
53 |
+ |
|
54 |
+ internal func apply(for configure: NavigationBarConfiguration) { |
|
55 |
+ isHidden = configure.isHidden |
|
56 |
+ isTranslucent = configure.isTranslucent |
|
57 |
+ |
|
58 |
+ barStyle = configure.barStyle |
|
59 |
+ shadowImage = configure.shadowImage |
|
60 |
+ setBackgroundImage(configure.backgroundImage, for: .default) |
|
107 | 61 |
} |
108 |
- |
|
109 |
- override func value(forUndefinedKey key: String) -> Any? { |
|
110 |
- return nil |
|
62 |
+ |
|
63 |
+ internal convenience init(configure: NavigationBarConfiguration) { |
|
64 |
+ self.init() |
|
65 |
+ apply(for: configure) |
|
111 | 66 |
} |
112 | 67 |
} |
113 | 68 |
|
114 |
-/// NavigationBar transition |
|
115 |
-extension NavigationBar { |
|
116 |
- func constructViewHierarchy() { |
|
117 |
- setupShadowView() |
|
118 |
- setupBackgroundImageView() |
|
119 |
- |
|
120 |
- guard let barBackground = getBarBackground() else { return } |
|
121 |
- |
|
122 |
- insertSubview(shadowImageView, aboveSubview: barBackground) |
|
123 |
- insertSubview(backgroundImageView, aboveSubview: barBackground) |
|
124 |
- insertSubview(fakeView, belowSubview: backgroundImageView) |
|
125 |
- layoutIfNeeded() |
|
126 |
- } |
|
127 |
- |
|
128 |
- private func setupShadowView() { |
|
129 |
- if let image = originShadowImage, image.size == CGSize.zero { |
|
130 |
- shadowImageView.image = image |
|
131 |
- } else { |
|
132 |
- shadowImageView.backgroundColor = UIColor(red: 0, green: 0, blue: 0, |
|
133 |
- alpha: 77.0 / 255) |
|
134 |
- } |
|
135 |
- |
|
136 |
- shadowImageView.alpha = originShadowImage == nil ? 1 : 0 |
|
137 |
- getShadowView()?.isHidden = true |
|
138 |
- } |
|
139 |
- |
|
140 |
- private func setupBackgroundImageView() { |
|
141 |
- if isPush { |
|
142 |
- fakeView.alpha = 0 |
|
143 |
- backgroundImageView.image = targetBgImage |
|
144 |
- } else { |
|
145 |
- setBackgroundImage() |
|
146 |
- fakeView.alpha = 1 |
|
147 |
- backgroundImageView.image = currBgImage |
|
148 |
- } |
|
149 |
- } |
|
150 |
- |
|
151 |
- /// interactivePopGestureRecognizer |
|
152 |
- func transitionAnimationWithPercent(_ percent: CGFloat) { |
|
153 |
- switch bounce { |
|
154 |
- case .forward, .none: |
|
155 |
- transitionShadowAnimationWithPercent(percent) |
|
156 |
- transitionBackgroundAnimationWithPercent(percent) |
|
157 |
- case .backward: |
|
158 |
- transitionShadowAnimationWithPercent(1 - percent) |
|
159 |
- transitionBackgroundAnimationWithPercent(1 - percent) |
|
160 |
- } |
|
161 |
- } |
|
162 |
- |
|
163 |
- func transitionAnimation() { |
|
164 |
- transitionShadowAnimation() |
|
165 |
- transitionBackgroundAnimation() |
|
166 |
- } |
|
167 |
- |
|
168 |
- private func transitionShadowAnimation() { |
|
169 |
- guard hasChangedShadow else { return } |
|
170 |
- shadowImageView.alpha = originShadowImage == nil ? 0 : 1 |
|
171 |
-// if originShadowImage == nil { |
|
172 |
-// shadowImageView.alpha = isInteractive ? (1 - percent) * 1 : 0 |
|
173 |
-// } else { |
|
174 |
-// shadowImageView.alpha = isInteractive ? percent * 1 : 1 |
|
175 |
-// } |
|
69 |
+public extension UIToolbar { |
|
70 |
+ func getBarBackground() -> UIView? { |
|
71 |
+ return value(forKeyPath: "_backgroundView") as? UIView |
|
176 | 72 |
} |
177 |
- |
|
178 |
- private func transitionBackgroundAnimation() { |
|
179 |
- guard hasChangedBgImage else { return } |
|
180 |
- if isPush { |
|
181 |
- fakeView.alpha = 1 |
|
182 |
- backgroundImageView.frame.origin.x = 0 |
|
183 |
- } else { |
|
184 |
- fakeView.alpha = 0 |
|
185 |
- backgroundImageView.frame.origin.x = bounds.width |
|
73 |
+ |
|
74 |
+ func getShadowView() -> UIView? { |
|
75 |
+ guard let barBackground = getBarBackground() else { return nil } |
|
76 |
+ for view in barBackground.subviews where view.bounds.height == 0.5 { |
|
77 |
+ return view |
|
186 | 78 |
} |
79 |
+ return nil |
|
187 | 80 |
} |
188 |
- |
|
189 |
- private func transitionShadowAnimationWithPercent(_ percent: CGFloat) { |
|
190 |
- guard hasChangedShadow else { return } |
|
191 |
- shadowImageView.alpha = originShadowImage == nil ? (1 - percent) * 1 : percent * 1 |
|
192 |
- } |
|
193 |
- |
|
194 |
- private func transitionBackgroundAnimationWithPercent(_ percent: CGFloat) { |
|
195 |
- guard hasChangedBgImage else { return } |
|
196 |
- fakeView.alpha = (1 - percent) * 1 |
|
197 |
- backgroundImageView.frame.origin.x = percent * bounds.width |
|
198 |
- } |
|
199 |
- |
|
200 |
- func clear() { |
|
201 |
- |
|
202 |
- if isPush && hasChangedBgImage { setBackgroundImage() } |
|
203 |
- |
|
204 |
- if !isPush && bounce == .backward && hasChangedBgImage { |
|
205 |
- targetBgImage = currBgImage |
|
206 |
- setBackgroundImage() |
|
207 |
- } |
|
208 |
- |
|
209 |
- getShadowView()?.isHidden = false |
|
210 |
- |
|
211 |
- fakeView.removeFromSuperview() |
|
212 |
- shadowImageView.removeFromSuperview() |
|
213 |
- backgroundImageView.removeFromSuperview() |
|
214 |
- |
|
215 |
- currBgImage = nil |
|
216 |
- targetBgImage = nil |
|
217 |
- |
|
218 |
- hasChangedBgImage = false |
|
219 |
- hasChangedShadow = false |
|
220 |
- |
|
221 |
- bounce = .none |
|
81 |
+ |
|
82 |
+ internal convenience init(configure: NavigationBarConfiguration) { |
|
83 |
+ self.init() |
|
84 |
+ isHidden = configure.isHidden |
|
85 |
+ isTranslucent = configure.isTranslucent |
|
86 |
+ |
|
87 |
+ barStyle = configure.barStyle |
|
88 |
+ setShadowImage(configure.shadowImage, forToolbarPosition: .any) |
|
89 |
+ setBackgroundImage(configure.backgroundImage, forToolbarPosition: .any, barMetrics: .default) |
|
222 | 90 |
} |
223 | 91 |
} |
224 | 92 |
|
225 |
-extension NavigationBar { |
|
226 |
- enum Bounce { |
|
227 |
- case none |
|
228 |
- case backward |
|
229 |
- case forward |
|
93 |
+extension UIViewController { |
|
94 |
+ internal func getFakeBarFrame(for navigationBar: UINavigationBar) -> CGRect? { |
|
95 |
+ guard let backgroundView = navigationBar.getBarBackground(), |
|
96 |
+ var frame = backgroundView.superview?.convert(backgroundView.frame, to: self.view) |
|
97 |
+ else { return nil } |
|
98 |
+ |
|
99 |
+ frame.origin.x = self.view.bounds.origin.x |
|
100 |
+ return frame |
|
230 | 101 |
} |
231 | 102 |
} |
@@ -0,0 +1,50 @@ |
||
1 |
+// |
|
2 |
+// NavigationBarConfiguration.swift |
|
3 |
+// PaiaiUIKit |
|
4 |
+// |
|
5 |
+// Created by ffib on 2019/5/8. |
|
6 |
+// Copyright © 2019 FFIB. All rights reserved. |
|
7 |
+// |
|
8 |
+ |
|
9 |
+import UIKit |
|
10 |
+ |
|
11 |
+struct NavigationBarConfiguration { |
|
12 |
+ var isHidden: Bool |
|
13 |
+ var isTranslucent: Bool |
|
14 |
+ |
|
15 |
+ var barStyle: UIBarStyle |
|
16 |
+ var shadowImage: UIImage? |
|
17 |
+ var backgroundImage: UIImage? |
|
18 |
+ |
|
19 |
+ static var `default`: NavigationBarConfiguration { |
|
20 |
+ return NavigationBarConfiguration() |
|
21 |
+ } |
|
22 |
+ |
|
23 |
+ static var transparent: NavigationBarConfiguration { |
|
24 |
+ return NavigationBarConfiguration(isHidden: false, isTranslucent: true, |
|
25 |
+ shadowImage: UIImage(), backgroundImage: UIImage()) |
|
26 |
+ } |
|
27 |
+ |
|
28 |
+ init(isHidden: Bool = false, |
|
29 |
+ isTranslucent: Bool = false, |
|
30 |
+ tintColor: UIColor = .black, |
|
31 |
+ shadowImage: UIImage? = nil, |
|
32 |
+ barTintColor: UIColor? = nil, |
|
33 |
+ backgroundImage: UIImage? = nil, |
|
34 |
+ barStyle: UIBarStyle = .default, |
|
35 |
+ titleTextAttributes: [NSAttributedString.Key: Any] = [:]) { |
|
36 |
+ self.isHidden = isHidden |
|
37 |
+ self.barStyle = barStyle |
|
38 |
+ self.shadowImage = shadowImage |
|
39 |
+ self.isTranslucent = isTranslucent |
|
40 |
+ self.backgroundImage = backgroundImage |
|
41 |
+ } |
|
42 |
+ |
|
43 |
+ init(navigationBar: UINavigationBar) { |
|
44 |
+ isHidden = navigationBar.isHidden |
|
45 |
+ barStyle = navigationBar.barStyle |
|
46 |
+ shadowImage = navigationBar.shadowImage |
|
47 |
+ isTranslucent = navigationBar.isTranslucent |
|
48 |
+ backgroundImage = navigationBar.backgroundImage(for: .default) |
|
49 |
+ } |
|
50 |
+} |
@@ -9,7 +9,13 @@ |
||
9 | 9 |
import UIKit |
10 | 10 |
|
11 | 11 |
public class NavigationController: UINavigationController { |
12 |
- |
|
12 |
+ |
|
13 |
+ private var operation: Operation = .none |
|
14 |
+ private var barConfigures: [UIViewController?: NavigationBarConfiguration] = [:] |
|
15 |
+ |
|
16 |
+ private var _fromFakeBar = UIToolbar() |
|
17 |
+ private var _toFakeBar = UIToolbar() |
|
18 |
+ |
|
13 | 19 |
override public init(rootViewController: UIViewController) { |
14 | 20 |
super.init(navigationBarClass: NavigationBar.classForCoder(), toolbarClass: nil) |
15 | 21 |
self.viewControllers = [rootViewController] |
@@ -28,41 +34,67 @@ public class NavigationController: UINavigationController { |
||
28 | 34 |
delegate = self |
29 | 35 |
interactivePopGestureRecognizer?.delegate = self |
30 | 36 |
interactivePopGestureRecognizer?.isEnabled = true |
31 |
- |
|
32 |
- interactivePopGestureRecognizer?.addTarget(self, |
|
33 |
- action: #selector(handlePop(gestureRecognizer:))) |
|
34 | 37 |
} |
38 |
+ |
|
39 |
+ public override func viewDidLayoutSubviews() { |
|
40 |
+ super.viewDidLayoutSubviews() |
|
41 |
+ if operation == .none { return } |
|
42 |
+ navigationBar.getBarBackground()?.alpha = 0 |
|
43 |
+ } |
|
44 |
+} |
|
35 | 45 |
|
36 |
- @objc |
|
37 |
- private func handlePop(gestureRecognizer: UIPanGestureRecognizer) { |
|
38 |
- guard let navBar = navigationBar as? NavigationBar else { return } |
|
39 |
- if gestureRecognizer.state == .began { navBar.isPush = false } |
|
40 |
- |
|
41 |
- guard navBar.needsInteractive else { return } |
|
42 |
- |
|
43 |
- let percent = gestureRecognizer.translation(in: view).x / view.bounds.width |
|
44 |
- |
|
45 |
- if gestureRecognizer.state == .began || gestureRecognizer.state == .changed { |
|
46 |
- navBar.transitionAnimationWithPercent(percent) |
|
46 |
+fileprivate extension NavigationController { |
|
47 |
+ |
|
48 |
+ func setFakeNavigationBar() { |
|
49 |
+ UIView.setAnimationsEnabled(false) |
|
50 |
+ guard let to = transitionCoordinator?.viewController(forKey: .to), |
|
51 |
+ let from = transitionCoordinator?.viewController(forKey: .from) else { return } |
|
52 |
+ |
|
53 |
+ switch self.operation { |
|
54 |
+ case .push: |
|
55 |
+ barConfigures[to] = NavigationBarConfiguration(navigationBar: navigationBar) |
|
56 |
+ case .pop: |
|
57 |
+ navigationBar.setBackgroundImage(barConfigures[to]?.backgroundImage, for: .default) |
|
58 |
+ default: |
|
59 |
+ break |
|
47 | 60 |
} |
61 |
+ |
|
62 |
+ setToFakeNavigationBar(for: to) |
|
63 |
+ setFromFakeNavigationBar(for: from) |
|
64 |
+ |
|
65 |
+ navigationBar.apply(for: .transparent) |
|
66 |
+ UIView.setAnimationsEnabled(true) |
|
67 |
+ |
|
68 |
+ if barConfigures[to]?.isHidden != barConfigures[from]?.isHidden { |
|
69 |
+ setNavigationBarHidden(barConfigures[to]?.isHidden ?? false, animated: true) |
|
70 |
+ } |
|
71 |
+ } |
|
48 | 72 |
|
49 |
- guard gestureRecognizer.state == .ended |
|
50 |
- || gestureRecognizer.state == .cancelled |
|
51 |
- || gestureRecognizer.state == .failed, |
|
52 |
- let coordinator = transitionCoordinator else { return } |
|
53 |
- |
|
54 |
- navBar.bounce = percent < 0.5 ? .backward : .forward |
|
55 |
- let durationPercent = Double(percent < 0.5 ? coordinator.percentComplete : (1 - coordinator.percentComplete)) |
|
56 |
- UIView.animate(withDuration: coordinator.transitionDuration * durationPercent, |
|
57 |
- delay: 0, |
|
58 |
- usingSpringWithDamping: 1, |
|
59 |
- initialSpringVelocity: coordinator.completionVelocity, |
|
60 |
- options: [], |
|
61 |
- animations: { |
|
62 |
- navBar.transitionAnimationWithPercent(1) |
|
63 |
- }, completion: { _ in |
|
64 |
- navBar.clear() |
|
65 |
- }) |
|
73 |
+ func setFromFakeNavigationBar(for from: UIViewController) { |
|
74 |
+ if let navBarFrame = from.getFakeBarFrame(for: navigationBar) { |
|
75 |
+ _fromFakeBar = UIToolbar(configure: barConfigures[from] ?? .default) |
|
76 |
+ _fromFakeBar.delegate = self |
|
77 |
+ _fromFakeBar.frame = navBarFrame |
|
78 |
+ from.view.addSubview(_fromFakeBar) |
|
79 |
+ } |
|
80 |
+ } |
|
81 |
+ |
|
82 |
+ func setToFakeNavigationBar(for to: UIViewController) { |
|
83 |
+ if let navBarFrame = to.getFakeBarFrame(for: navigationBar) { |
|
84 |
+ _toFakeBar = UIToolbar(configure: barConfigures[to] ?? .default) |
|
85 |
+ _toFakeBar.delegate = self |
|
86 |
+ _toFakeBar.frame = navBarFrame |
|
87 |
+ to.view.addSubview(_toFakeBar) |
|
88 |
+ } |
|
89 |
+ } |
|
90 |
+ |
|
91 |
+ func clearFake() { |
|
92 |
+ _fromFakeBar.removeFromSuperview() |
|
93 |
+ _toFakeBar.removeFromSuperview() |
|
94 |
+ |
|
95 |
+ guard let from = transitionCoordinator?.viewController(forKey: .from), |
|
96 |
+ operation == .pop else { return } |
|
97 |
+ barConfigures.removeValue(forKey: from) |
|
66 | 98 |
} |
67 | 99 |
} |
68 | 100 |
|
@@ -72,37 +104,34 @@ extension NavigationController: UINavigationControllerDelegate { |
||
72 | 104 |
animationControllerFor operation: UINavigationController.Operation, |
73 | 105 |
from fromVC: UIViewController, |
74 | 106 |
to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? { |
75 |
- (navigationBar as? NavigationBar)?.isPush = operation == .push |
|
107 |
+ self.operation = operation |
|
76 | 108 |
return nil |
77 | 109 |
} |
78 | 110 |
|
79 | 111 |
public func navigationController(_ navigationController: UINavigationController, |
80 | 112 |
willShow viewController: UIViewController, |
81 | 113 |
animated: Bool) { |
82 |
- guard let navBar = navigationBar as? NavigationBar, |
|
83 |
- navBar.needsInteractive else { return } |
|
84 |
- |
|
85 |
- guard let coordinator = transitionCoordinator, |
|
86 |
- animated else { |
|
87 |
- navBar.setBackgroundImage() |
|
88 |
- navBar.clear() |
|
89 |
- return |
|
114 |
+ if operation == .none { |
|
115 |
+ self.barConfigures[viewController] = NavigationBarConfiguration(navigationBar: navigationBar) |
|
116 |
+ return |
|
90 | 117 |
} |
91 |
- |
|
92 |
- navBar.constructViewHierarchy() |
|
93 |
- |
|
94 |
- guard !coordinator.isInteractive else { return } |
|
95 |
- |
|
96 |
- coordinator.animate(alongsideTransition: { (transitionContext) in |
|
97 |
- DispatchQueue.main.async { |
|
98 |
- UIView.beginAnimations(nil, context: nil) |
|
99 |
- UIView.setAnimationCurve(transitionContext.completionCurve) |
|
100 |
- UIView.setAnimationDuration(transitionContext.transitionDuration) |
|
101 |
- navBar.transitionAnimation() |
|
102 |
- UIView.commitAnimations() |
|
118 |
+ |
|
119 |
+ transitionCoordinator?.animate(alongsideTransition: { context in |
|
120 |
+ if context.isInteractive { |
|
121 |
+ self.operation = .pop |
|
122 |
+ } |
|
123 |
+ self.setFakeNavigationBar() |
|
124 |
+ }, completion: { context in |
|
125 |
+ let vc: UIViewController? |
|
126 |
+ if context.isCancelled { |
|
127 |
+ self.operation = .push |
|
128 |
+ vc = context.viewController(forKey: .from) |
|
129 |
+ } else { |
|
130 |
+ vc = context.viewController(forKey: .to) |
|
103 | 131 |
} |
104 |
- }, completion: { (_) in |
|
105 |
- navBar.clear() |
|
132 |
+ self.navigationBar.getBarBackground()?.alpha = 1 |
|
133 |
+ self.navigationBar.apply(for: self.barConfigures[vc] ?? .default) |
|
134 |
+ self.clearFake() |
|
106 | 135 |
}) |
107 | 136 |
} |
108 | 137 |
} |
@@ -115,3 +144,9 @@ extension NavigationController: UIGestureRecognizerDelegate { |
||
115 | 144 |
return true |
116 | 145 |
} |
117 | 146 |
} |
147 |
+ |
|
148 |
+extension NavigationController: UIToolbarDelegate { |
|
149 |
+ public func position(for bar: UIBarPositioning) -> UIBarPosition { |
|
150 |
+ return .top |
|
151 |
+ } |
|
152 |
+} |
@@ -69,7 +69,9 @@ open class PageViewController: UIViewController { |
||
69 | 69 |
contentRect = CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.height) |
70 | 70 |
|
71 | 71 |
if #available(iOS 11, *) { |
72 |
- scrollView.contentInsetAdjustmentBehavior = .never |
|
72 |
+ scrollView.contentInsetAdjustmentBehavior = .automatic |
|
73 |
+ } else { |
|
74 |
+ automaticallyAdjustsScrollViewInsets = false |
|
73 | 75 |
} |
74 | 76 |
|
75 | 77 |
constructViewHierarchy() |
@@ -82,14 +82,15 @@ import CoreImage |
||
82 | 82 |
} |
83 | 83 |
|
84 | 84 |
@objc func start() { |
85 |
- let queue = DispatchQueue(label: "FFIB.startScan.com") |
|
86 |
- queue.async { |
|
87 |
- self.qrscanner?.startScan() |
|
85 |
+// let queue = DispatchQueue(label: "FFIB.startScan.com") |
|
86 |
+// queue.async { |
|
87 |
+ |
|
88 | 88 |
DispatchQueue.main.async { |
89 |
+ self.qrscanner?.startScan() |
|
89 | 90 |
self.qrmaskView?.startAnimation() |
90 | 91 |
self.indicatorView.stopAnimating() |
91 | 92 |
} |
92 |
- } |
|
93 |
+// } |
|
93 | 94 |
} |
94 | 95 |
|
95 | 96 |
public func openLight() { |
@@ -83,7 +83,7 @@ class QRCodeScanner: NSObject { |
||
83 | 83 |
} |
84 | 84 |
func startScan() { |
85 | 85 |
setScanArea() |
86 |
- captureSession.startRunning() |
|
86 |
+// captureSession.startRunning() |
|
87 | 87 |
} |
88 | 88 |
|
89 | 89 |
func stopScan() { |
@@ -70,11 +70,13 @@ fileprivate extension AppCoordinator { |
||
70 | 70 |
|
71 | 71 |
let homeCoordinator = HomeCoordinator(homeVC, |
72 | 72 |
navigationController: navigationController, |
73 |
+ containerViewController: containerViewController, |
|
73 | 74 |
userInfoViewModel: shareUserInfoViewModel) |
74 | 75 |
coordinate(to: homeCoordinator).subscribe().disposed(by: disposeBag) |
75 | 76 |
|
76 | 77 |
let messageCoordinator = MessageCoordinator(messageVC, |
77 |
- navigationController: navigationController) |
|
78 |
+ navigationController: navigationController, |
|
79 |
+ containerViewController: containerViewController) |
|
78 | 80 |
coordinate(to: messageCoordinator).subscribe().disposed(by: disposeBag) |
79 | 81 |
|
80 | 82 |
containerViewController.pageItems = [PageItem(title: "首页", |
@@ -61,6 +61,7 @@ public final class ContainerViewController: PageViewController { |
||
61 | 61 |
} |
62 | 62 |
|
63 | 63 |
func setupNavigationBar() { |
64 |
+ navigationController?.navigationBar.isTranslucent = true |
|
64 | 65 |
navigationController?.navigationBar.shadowImage = UIImage() |
65 | 66 |
navigationController?.navigationBar.tintColor = UIColor.white |
66 | 67 |
navigationController?.navigationBar.barTintColor = UIColor.white |
@@ -52,10 +52,10 @@ final class GroupViewController: UIViewController { |
||
52 | 52 |
override func viewDidLoad() { |
53 | 53 |
super.viewDidLoad() |
54 | 54 |
initalize() |
55 |
+ navigationController?.navigationBar.setBackgroundImage(UIImage.Navigation.background, for: .default) |
|
55 | 56 |
} |
56 | 57 |
|
57 | 58 |
override func viewWillAppear(_ animated: Bool) { |
58 |
- navigationController?.navigationBar.setBackgroundImage(UIImage.Navigation.background, for: .default) |
|
59 | 59 |
super.viewWillAppear(animated) |
60 | 60 |
} |
61 | 61 |
|
@@ -82,7 +82,7 @@ final class GroupViewController: UIViewController { |
||
82 | 82 |
} |
83 | 83 |
|
84 | 84 |
deinit { |
85 |
- collectionView.endAllRefreshing() |
|
85 |
+ collectionView.removeAllPullToRefresh() |
|
86 | 86 |
} |
87 | 87 |
} |
88 | 88 |
|
@@ -13,14 +13,16 @@ import PaiaiDataKit |
||
13 | 13 |
class HomeCoordinator: BaseCoordinator<Void> { |
14 | 14 |
|
15 | 15 |
var homeViewController: HomeViewController |
16 |
+ var containerViewController: ContainerViewController |
|
16 | 17 |
var shareUserInfoViewModel: UserInfoViewModel |
17 | 18 |
|
18 | 19 |
init(_ viewController: HomeViewController, |
19 | 20 |
navigationController: UINavigationController, |
21 |
+ containerViewController: ContainerViewController, |
|
20 | 22 |
userInfoViewModel: UserInfoViewModel) { |
21 | 23 |
self.homeViewController = viewController |
22 | 24 |
self.shareUserInfoViewModel = userInfoViewModel |
23 |
- |
|
25 |
+ self.containerViewController = containerViewController |
|
24 | 26 |
super.init(navigationController: navigationController, viewController: viewController) |
25 | 27 |
} |
26 | 28 |
|
@@ -36,7 +36,7 @@ final class HomeViewController: UIViewController { |
||
36 | 36 |
collectionView.register(UINib(nibName: "PhotoCell", |
37 | 37 |
bundle: Bundle(identifier: "com.Paiai-iOS")), |
38 | 38 |
forCellWithReuseIdentifier: "photoCell") |
39 |
- |
|
39 |
+ |
|
40 | 40 |
setup() |
41 | 41 |
binding() |
42 | 42 |
} |
@@ -62,7 +62,7 @@ final class HomeViewController: UIViewController { |
||
62 | 62 |
} |
63 | 63 |
|
64 | 64 |
deinit { |
65 |
- collectionView.endAllRefreshing() |
|
65 |
+ collectionView.removeAllPullToRefresh() |
|
66 | 66 |
} |
67 | 67 |
} |
68 | 68 |
|
@@ -23,6 +23,7 @@ final class ScanQRViewController: UIViewController { |
||
23 | 23 |
override func viewDidLoad() { |
24 | 24 |
super.viewDidLoad() |
25 | 25 |
scanView.delegate = self |
26 |
+ setNavigationBar() |
|
26 | 27 |
viewModel.join(code: "http://pai.ai/g/SpA5be3") |
27 | 28 |
} |
28 | 29 |
|
@@ -32,8 +33,8 @@ final class ScanQRViewController: UIViewController { |
||
32 | 33 |
} |
33 | 34 |
|
34 | 35 |
override func viewWillAppear(_ animated: Bool) { |
35 |
- setNavigationBar() |
|
36 | 36 |
super.viewWillAppear(animated) |
37 |
+ |
|
37 | 38 |
} |
38 | 39 |
|
39 | 40 |
override func viewWillDisappear(_ animated: Bool) { |
@@ -14,7 +14,8 @@ class MessageCoordinator: BaseCoordinator<Void> { |
||
14 | 14 |
fileprivate let messageViewController: MessageViewController |
15 | 15 |
|
16 | 16 |
init(_ viewController: MessageViewController, |
17 |
- navigationController: UINavigationController) { |
|
17 |
+ navigationController: UINavigationController, |
|
18 |
+ containerViewController: ContainerViewController) { |
|
18 | 19 |
messageViewController = viewController |
19 | 20 |
super.init(navigationController: navigationController, viewController: viewController) |
20 | 21 |
} |
@@ -91,7 +91,7 @@ final class MessageListViewController: UIViewController { |
||
91 | 91 |
} |
92 | 92 |
|
93 | 93 |
deinit { |
94 |
- tableView.endAllRefreshing() |
|
94 |
+ tableView.removeAllPullToRefresh() |
|
95 | 95 |
} |
96 | 96 |
} |
97 | 97 |
|
@@ -58,7 +58,7 @@ final class MineGroupViewController: UIViewController { |
||
58 | 58 |
} |
59 | 59 |
|
60 | 60 |
deinit { |
61 |
- tableView.endAllRefreshing() |
|
61 |
+ tableView.removeAllPullToRefresh() |
|
62 | 62 |
} |
63 | 63 |
} |
64 | 64 |
|
@@ -55,7 +55,7 @@ final class MineOrderViewController: UIViewController { |
||
55 | 55 |
} |
56 | 56 |
|
57 | 57 |
deinit { |
58 |
- tableView.endAllRefreshing() |
|
58 |
+ tableView.removeAllPullToRefresh() |
|
59 | 59 |
} |
60 | 60 |
} |
61 | 61 |
|