Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactoring: fix message animation #90

Merged
merged 3 commits into from
Jan 26, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions BarcodeScanner.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@
D5B2E89B1C3A780C00C0327D /* Frameworks */,
D5B2E89C1C3A780C00C0327D /* Headers */,
D5B2E89D1C3A780C00C0327D /* Resources */,
D5C113C9201A981500D46C9C /* SwiftLint */,
);
buildRules = (
);
Expand Down Expand Up @@ -221,6 +222,23 @@
};
/* End PBXResourcesBuildPhase section */

/* Begin PBXShellScriptBuildPhase section */
D5C113C9201A981500D46C9C /* SwiftLint */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = SwiftLint;
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "if which swiftlint >/dev/null; then\nswiftlint\nelse\necho \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi";
};
/* End PBXShellScriptBuildPhase section */

/* Begin PBXSourcesBuildPhase section */
D5B2E89A1C3A780C00C0327D /* Sources */ = {
isa = PBXSourcesBuildPhase;
Expand Down
67 changes: 43 additions & 24 deletions Sources/Controllers/BarcodeScannerViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@ open class BarcodeScannerViewController: UIViewController {
/// Camera view with custom buttons.
public private(set) lazy var cameraViewController: CameraViewController = .init()

// Constraints that are activated when the view is used as a footer.
private lazy var collapsedConstraints: [NSLayoutConstraint] = self.makeCollapsedMessageConstraints()
// Constraints that are activated when the view is used for loading animation and error messages.
private lazy var expandedConstraints: [NSLayoutConstraint] = self.makeExpandedMessageConstraints()

private var messageView: UIView {
return messageViewController.view
}
Expand All @@ -76,38 +81,26 @@ open class BarcodeScannerViewController: UIViewController {
}
}

/// Calculated frame for the info view.
private var messageViewFrame: CGRect {
let height = status.state != .processing ? 75 : view.bounds.height
return CGRect(
x: 0, y: view.bounds.height - height,
width: view.bounds.width, height: height
)
}

// MARK: - View lifecycle

open override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.black

add(childViewController: messageViewController)
messageView.translatesAutoresizingMaskIntoConstraints = false
collapsedConstraints.activate()

cameraViewController.metadata = metadata
cameraViewController.delegate = self

add(childViewController: cameraViewController)
add(childViewController: messageViewController)

view.bringSubview(toFront: messageView)
}

open override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
setupConstraints()
}

open override func viewWillTransition(to size: CGSize,
with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
coordinator.animate(alongsideTransition: { (context) in
self.messageView.frame = self.messageViewFrame
})
setupCameraConstraints()
}

// MARK: - State handling
Expand Down Expand Up @@ -147,13 +140,20 @@ open class BarcodeScannerViewController: UIViewController {
resetState()
}

if newValue.state != .processing {
expandedConstraints.deactivate()
collapsedConstraints.activate()
} else {
collapsedConstraints.deactivate()
expandedConstraints.activate()
}

messageViewController.state = newValue.state

UIView.animate(
withDuration: duration,
animations: ({
self.messageView.layoutIfNeeded()
self.messageView.frame = self.messageViewFrame
self.view.layoutIfNeeded()
}),
completion: ({ [weak self] _ in
if delayReset {
Expand Down Expand Up @@ -209,11 +209,12 @@ open class BarcodeScannerViewController: UIViewController {
// MARK: - Layout

private extension BarcodeScannerViewController {
private func setupConstraints() {
guard constraintsActivated else {
private func setupCameraConstraints() {
guard !constraintsActivated else {
return
}

constraintsActivated = true
let cameraView = cameraViewController.view!

NSLayoutConstraint.activate(
Expand All @@ -239,6 +240,24 @@ private extension BarcodeScannerViewController {
)
}
}

private func makeExpandedMessageConstraints() -> [NSLayoutConstraint] {
return [
messageView.topAnchor.constraint(equalTo: view.topAnchor),
messageView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
messageView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
messageView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
]
}

private func makeCollapsedMessageConstraints() -> [NSLayoutConstraint] {
return [
messageView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
messageView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
messageView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
messageView.heightAnchor.constraint(equalToConstant: 75)
]
}
}

// MARK: - HeaderViewControllerDelegate
Expand Down
25 changes: 14 additions & 11 deletions Sources/Controllers/CameraViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -114,11 +114,13 @@ public final class CameraViewController: UIViewController {
public override func viewWillTransition(to size: CGSize,
with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
coordinator.animate(alongsideTransition: { [weak self] _ in
self?.setupVideoPreviewLayerOrientation()
}) { [weak self] _ in
self?.animateFocusView()
}
coordinator.animate(
alongsideTransition: { [weak self] _ in
self?.setupVideoPreviewLayerOrientation()
},
completion: ({ [weak self] _ in
self?.animateFocusView()
}))
}

// MARK: - Video capturing
Expand Down Expand Up @@ -218,11 +220,12 @@ public final class CameraViewController: UIViewController {
return
}

regularFocusViewConstraints.forEach({ $0.isActive = false })
animatedFocusViewConstraints.forEach({ $0.isActive = true })
regularFocusViewConstraints.deactivate()
animatedFocusViewConstraints.activate()

UIView.animate(
withDuration: 1.0, delay:0,
withDuration: 1.0,
delay: 0,
options: [.repeat, .autoreverse, .beginFromCurrentState],
animations: ({ [weak self] in
self?.view.layoutIfNeeded()
Expand Down Expand Up @@ -300,7 +303,7 @@ private extension CameraViewController {
videoPreviewLayer.frame = view.layer.bounds

if let connection = videoPreviewLayer.connection, connection.isVideoOrientationSupported {
switch (UIApplication.shared.statusBarOrientation) {
switch UIApplication.shared.statusBarOrientation {
case .portrait:
connection.videoOrientation = .portrait
case .landscapeRight:
Expand Down Expand Up @@ -336,7 +339,7 @@ private extension CameraViewController {
let button = UIButton(type: .system)
let title = NSAttributedString(
string: localizedString("BUTTON_SETTINGS"),
attributes: [.font: UIFont.boldSystemFont(ofSize: 17), .foregroundColor : UIColor.white]
attributes: [.font: UIFont.boldSystemFont(ofSize: 17), .foregroundColor: UIColor.white]
)
button.setAttributedTitle(title, for: UIControlState())
button.sizeToFit()
Expand Down
10 changes: 5 additions & 5 deletions Sources/Controllers/MessageViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -142,11 +142,11 @@ public final class MessageViewController: UIViewController {
}

if state == .scanning || state == .unauthorized {
expandedConstraints.forEach({ $0.isActive = false })
collapsedConstraints.forEach({ $0.isActive = true })
expandedConstraints.deactivate()
collapsedConstraints.activate()
} else {
collapsedConstraints.forEach({ $0.isActive = false })
expandedConstraints.forEach({ $0.isActive = true })
collapsedConstraints.deactivate()
expandedConstraints.activate()
}
}
}
Expand All @@ -164,7 +164,7 @@ extension MessageViewController {
imageView.widthAnchor.constraint(equalToConstant: 30),
imageView.heightAnchor.constraint(equalToConstant: 27),

textLabel.topAnchor.constraint(equalTo: imageView.bottomAnchor, constant: 14),
textLabel.topAnchor.constraint(equalTo: imageView.bottomAnchor, constant: 18),
textLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: padding),
textLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -padding),

Expand Down
18 changes: 18 additions & 0 deletions Sources/Extensions/NSLayoutConstraint+Extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,21 @@ extension NSLayoutConstraint {
}
}
}

extension Array where Element: NSLayoutConstraint {
func activate() {
forEach {
if !$0.isActive {
$0.isActive = true
}
}
}

func deactivate() {
forEach {
if $0.isActive {
$0.isActive = false
}
}
}
}