Skip to content

Commit 515d0cd

Browse files
authored
Merge pull request #90 from hyperoslo/fix/message-animation
Refactoring: fix message animation
2 parents 752dbe6 + 3aafc30 commit 515d0cd

File tree

5 files changed

+98
-40
lines changed

5 files changed

+98
-40
lines changed

BarcodeScanner.xcodeproj/project.pbxproj

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@
166166
D5B2E89B1C3A780C00C0327D /* Frameworks */,
167167
D5B2E89C1C3A780C00C0327D /* Headers */,
168168
D5B2E89D1C3A780C00C0327D /* Resources */,
169+
D5C113C9201A981500D46C9C /* SwiftLint */,
169170
);
170171
buildRules = (
171172
);
@@ -221,6 +222,23 @@
221222
};
222223
/* End PBXResourcesBuildPhase section */
223224

225+
/* Begin PBXShellScriptBuildPhase section */
226+
D5C113C9201A981500D46C9C /* SwiftLint */ = {
227+
isa = PBXShellScriptBuildPhase;
228+
buildActionMask = 2147483647;
229+
files = (
230+
);
231+
inputPaths = (
232+
);
233+
name = SwiftLint;
234+
outputPaths = (
235+
);
236+
runOnlyForDeploymentPostprocessing = 0;
237+
shellPath = /bin/sh;
238+
shellScript = "if which swiftlint >/dev/null; then\nswiftlint\nelse\necho \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi";
239+
};
240+
/* End PBXShellScriptBuildPhase section */
241+
224242
/* Begin PBXSourcesBuildPhase section */
225243
D5B2E89A1C3A780C00C0327D /* Sources */ = {
226244
isa = PBXSourcesBuildPhase;

Sources/Controllers/BarcodeScannerViewController.swift

Lines changed: 43 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@ open class BarcodeScannerViewController: UIViewController {
6565
/// Camera view with custom buttons.
6666
public private(set) lazy var cameraViewController: CameraViewController = .init()
6767

68+
// Constraints that are activated when the view is used as a footer.
69+
private lazy var collapsedConstraints: [NSLayoutConstraint] = self.makeCollapsedMessageConstraints()
70+
// Constraints that are activated when the view is used for loading animation and error messages.
71+
private lazy var expandedConstraints: [NSLayoutConstraint] = self.makeExpandedMessageConstraints()
72+
6873
private var messageView: UIView {
6974
return messageViewController.view
7075
}
@@ -76,38 +81,26 @@ open class BarcodeScannerViewController: UIViewController {
7681
}
7782
}
7883

79-
/// Calculated frame for the info view.
80-
private var messageViewFrame: CGRect {
81-
let height = status.state != .processing ? 75 : view.bounds.height
82-
return CGRect(
83-
x: 0, y: view.bounds.height - height,
84-
width: view.bounds.width, height: height
85-
)
86-
}
87-
8884
// MARK: - View lifecycle
8985

9086
open override func viewDidLoad() {
9187
super.viewDidLoad()
9288
view.backgroundColor = UIColor.black
89+
90+
add(childViewController: messageViewController)
91+
messageView.translatesAutoresizingMaskIntoConstraints = false
92+
collapsedConstraints.activate()
93+
9394
cameraViewController.metadata = metadata
9495
cameraViewController.delegate = self
95-
9696
add(childViewController: cameraViewController)
97-
add(childViewController: messageViewController)
97+
98+
view.bringSubview(toFront: messageView)
9899
}
99100

100101
open override func viewWillAppear(_ animated: Bool) {
101102
super.viewWillAppear(animated)
102-
setupConstraints()
103-
}
104-
105-
open override func viewWillTransition(to size: CGSize,
106-
with coordinator: UIViewControllerTransitionCoordinator) {
107-
super.viewWillTransition(to: size, with: coordinator)
108-
coordinator.animate(alongsideTransition: { (context) in
109-
self.messageView.frame = self.messageViewFrame
110-
})
103+
setupCameraConstraints()
111104
}
112105

113106
// MARK: - State handling
@@ -147,13 +140,20 @@ open class BarcodeScannerViewController: UIViewController {
147140
resetState()
148141
}
149142

143+
if newValue.state != .processing {
144+
expandedConstraints.deactivate()
145+
collapsedConstraints.activate()
146+
} else {
147+
collapsedConstraints.deactivate()
148+
expandedConstraints.activate()
149+
}
150+
150151
messageViewController.state = newValue.state
151152

152153
UIView.animate(
153154
withDuration: duration,
154155
animations: ({
155-
self.messageView.layoutIfNeeded()
156-
self.messageView.frame = self.messageViewFrame
156+
self.view.layoutIfNeeded()
157157
}),
158158
completion: ({ [weak self] _ in
159159
if delayReset {
@@ -209,11 +209,12 @@ open class BarcodeScannerViewController: UIViewController {
209209
// MARK: - Layout
210210

211211
private extension BarcodeScannerViewController {
212-
private func setupConstraints() {
213-
guard constraintsActivated else {
212+
private func setupCameraConstraints() {
213+
guard !constraintsActivated else {
214214
return
215215
}
216216

217+
constraintsActivated = true
217218
let cameraView = cameraViewController.view!
218219

219220
NSLayoutConstraint.activate(
@@ -239,6 +240,24 @@ private extension BarcodeScannerViewController {
239240
)
240241
}
241242
}
243+
244+
private func makeExpandedMessageConstraints() -> [NSLayoutConstraint] {
245+
return [
246+
messageView.topAnchor.constraint(equalTo: view.topAnchor),
247+
messageView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
248+
messageView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
249+
messageView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
250+
]
251+
}
252+
253+
private func makeCollapsedMessageConstraints() -> [NSLayoutConstraint] {
254+
return [
255+
messageView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
256+
messageView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
257+
messageView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
258+
messageView.heightAnchor.constraint(equalToConstant: 75)
259+
]
260+
}
242261
}
243262

244263
// MARK: - HeaderViewControllerDelegate

Sources/Controllers/CameraViewController.swift

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -114,11 +114,13 @@ public final class CameraViewController: UIViewController {
114114
public override func viewWillTransition(to size: CGSize,
115115
with coordinator: UIViewControllerTransitionCoordinator) {
116116
super.viewWillTransition(to: size, with: coordinator)
117-
coordinator.animate(alongsideTransition: { [weak self] _ in
118-
self?.setupVideoPreviewLayerOrientation()
119-
}) { [weak self] _ in
120-
self?.animateFocusView()
121-
}
117+
coordinator.animate(
118+
alongsideTransition: { [weak self] _ in
119+
self?.setupVideoPreviewLayerOrientation()
120+
},
121+
completion: ({ [weak self] _ in
122+
self?.animateFocusView()
123+
}))
122124
}
123125

124126
// MARK: - Video capturing
@@ -218,11 +220,12 @@ public final class CameraViewController: UIViewController {
218220
return
219221
}
220222

221-
regularFocusViewConstraints.forEach({ $0.isActive = false })
222-
animatedFocusViewConstraints.forEach({ $0.isActive = true })
223-
223+
regularFocusViewConstraints.deactivate()
224+
animatedFocusViewConstraints.activate()
225+
224226
UIView.animate(
225-
withDuration: 1.0, delay:0,
227+
withDuration: 1.0,
228+
delay: 0,
226229
options: [.repeat, .autoreverse, .beginFromCurrentState],
227230
animations: ({ [weak self] in
228231
self?.view.layoutIfNeeded()
@@ -300,7 +303,7 @@ private extension CameraViewController {
300303
videoPreviewLayer.frame = view.layer.bounds
301304

302305
if let connection = videoPreviewLayer.connection, connection.isVideoOrientationSupported {
303-
switch (UIApplication.shared.statusBarOrientation) {
306+
switch UIApplication.shared.statusBarOrientation {
304307
case .portrait:
305308
connection.videoOrientation = .portrait
306309
case .landscapeRight:
@@ -336,7 +339,7 @@ private extension CameraViewController {
336339
let button = UIButton(type: .system)
337340
let title = NSAttributedString(
338341
string: localizedString("BUTTON_SETTINGS"),
339-
attributes: [.font: UIFont.boldSystemFont(ofSize: 17), .foregroundColor : UIColor.white]
342+
attributes: [.font: UIFont.boldSystemFont(ofSize: 17), .foregroundColor: UIColor.white]
340343
)
341344
button.setAttributedTitle(title, for: UIControlState())
342345
button.sizeToFit()

Sources/Controllers/MessageViewController.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -142,11 +142,11 @@ public final class MessageViewController: UIViewController {
142142
}
143143

144144
if state == .scanning || state == .unauthorized {
145-
expandedConstraints.forEach({ $0.isActive = false })
146-
collapsedConstraints.forEach({ $0.isActive = true })
145+
expandedConstraints.deactivate()
146+
collapsedConstraints.activate()
147147
} else {
148-
collapsedConstraints.forEach({ $0.isActive = false })
149-
expandedConstraints.forEach({ $0.isActive = true })
148+
collapsedConstraints.deactivate()
149+
expandedConstraints.activate()
150150
}
151151
}
152152
}
@@ -164,7 +164,7 @@ extension MessageViewController {
164164
imageView.widthAnchor.constraint(equalToConstant: 30),
165165
imageView.heightAnchor.constraint(equalToConstant: 27),
166166

167-
textLabel.topAnchor.constraint(equalTo: imageView.bottomAnchor, constant: 14),
167+
textLabel.topAnchor.constraint(equalTo: imageView.bottomAnchor, constant: 18),
168168
textLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: padding),
169169
textLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -padding),
170170

Sources/Extensions/NSLayoutConstraint+Extensions.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,21 @@ extension NSLayoutConstraint {
1313
}
1414
}
1515
}
16+
17+
extension Array where Element: NSLayoutConstraint {
18+
func activate() {
19+
forEach {
20+
if !$0.isActive {
21+
$0.isActive = true
22+
}
23+
}
24+
}
25+
26+
func deactivate() {
27+
forEach {
28+
if $0.isActive {
29+
$0.isActive = false
30+
}
31+
}
32+
}
33+
}

0 commit comments

Comments
 (0)