SwiftyCam 捕获会话不是 运行
SwiftyCam capture session is not running
我已经按照 SwiftyCam Everything lays out correctly and is going well; however, when the camera button is pushed I get a message in the console saying "[SwiftyCam]: Cannot take photo. Capture session is not running". There have been other people having this problem with swift 4 and you can find that here. I have gone through the whole framework line by line but for some reason I can't figure it out. I would really appreciate it if someone could look at the framework and the documentation and help me out. The way I'm doing it is just about exactly how it's done in the Swift 4 demo project 上 GitHub 上的演示项目创建了我的相机视图,因此这将是代码参考。
提前致谢
编辑:下面是在 WelcomeVC
之后设置 SwipeNavigationController 时的代码
let swipeNavigationController = SwipeNavigationController(centerViewController: CameraViewController())
swipeNavigationController.topViewController = BlueView()
swipeNavigationController.bottomViewController = PinkView()
swipeNavigationController.leftViewController = OrangeView()
swipeNavigationController.rightViewController = GreenView()
cameraView.navigationController?.setNavigationBarHidden(true, animated: false)
orangeView.navigationController?.setNavigationBarHidden(false, animated: false)
greenView.navigationController?.setNavigationBarHidden(false, animated: false)
let navController = UINavigationController(rootViewController: swipeNavigationController)
self.present(navController, animated: true, completion: nil)
CameraVC中的全部代码如下
class CameraViewController: SwiftyCamViewController, SwiftyCamViewControllerDelegate, SwipeNavigationControllerDelegate {
let orangeVC = OrangeView()
let greenVC = GreenView()
let blueVC = BlueView()
let pinkVC = PinkView()
let flipCameraButton: UIButton = {
let button = UIButton()
let image = UIImage(named: "cameraSwitch")
button.setImage(image, for: .normal)
button.addTarget(self, action: #selector(cameraSwitchTapped), for: .touchUpInside)
return button
}()
let captureButton: SwiftyRecordButton = {
let button = SwiftyRecordButton(frame: CGRect(x: 150, y: 572, width: 75, height: 75))
//let image = UIImage(named: "focus")
//button.setImage(image, for: .normal)
//button.addTarget(self, action: #selector(cameraTapped), for: .touchUpInside)
return button
}()
let orangeButton: UIButton = {
let button = UIButton()
let image = UIImage(named: "OrangeIcon")
button.setImage(image, for: .normal)
button.addTarget(self, action: #selector(goToOrange), for: .touchUpInside)
return button
}()
let greenButton: UIButton = {
let button = UIButton()
let image = UIImage(named: "GreenIcon")
button.setImage(image, for: .normal)
button.addTarget(self, action: #selector(goToGreen), for: .touchUpInside)
return button
}()
let pinkButton: UIButton = {
let button = UIButton()
let image = UIImage(named: "pinkCameraIcon")
button.setImage(image, for: .normal)
button.addTarget(self, action: #selector(goToPink), for: .touchUpInside)
return button
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(flipCameraButton)
view.addSubview(captureButton)
view.addSubview(orangeButton)
view.addSubview(greenButton)
view.addSubview(pinkButton)
shouldPrompToAppSettings = true
cameraDelegate = self
maximumVideoDuration = 10.0
shouldUseDeviceOrientation = true
allowAutoRotate = true
audioEnabled = true
// disable capture button until session starts
captureButton.buttonEnabled = false
navigationController?.isNavigationBarHidden = true
UIApplication.shared.statusBarStyle = .lightContent
navigationController?.isNavigationBarHidden = true
setupViews()
}
override func viewWillAppear(_ animated: Bool) {
UIApplication.shared.statusBarStyle = .lightContent
navigationController?.isNavigationBarHidden = true
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
captureButton.delegate = self
}
//
@objc func goToOrange() {
orangeVC.navigationController?.setNavigationBarHidden(false, animated: true)
self.containerSwipeNavigationController?.showEmbeddedView(position: .left)
}
@objc func goToGreen() {
greenVC.navigationController?.setNavigationBarHidden(false, animated: true)
self.containerSwipeNavigationController?.showEmbeddedView(position: .right)
}
@objc func goToPink() {
self.containerSwipeNavigationController?.showEmbeddedView(position: .bottom)
}
@objc func cameraSwitchTapped() {
switchCamera()
}
@objc func cameraTapped() {
print("CAMERA TAPPED")
takePhoto()
}
func setupViews() {
flipCameraButton.anchor(top: view.topAnchor, left: nil, bottom: nil, right: view.rightAnchor, paddingTop: 25, paddingLeft: 0, paddingBottom: 0, paddingRight: 12, width: 35, height: 35)
captureButton.anchor(top: nil, left: nil, bottom: pinkButton.topAnchor, right: nil, paddingTop: 0, paddingLeft: 0, paddingBottom: 10, paddingRight: 0, width: 75, height: 75)
captureButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
orangeButton.anchor(top: nil, left: view.leftAnchor, bottom: view.bottomAnchor, right: nil, paddingTop: 0, paddingLeft: 10, paddingBottom: 0, paddingRight: 0, width: 75, height: 75)
greenButton.anchor(top: nil, left: nil, bottom: view.bottomAnchor, right: view.rightAnchor, paddingTop: 0, paddingLeft: 0, paddingBottom: 0, paddingRight: 10, width: 75, height: 75)
pinkButton.anchor(top: nil, left: nil, bottom: view.bottomAnchor, right: nil, paddingTop: 0, paddingLeft: 0, paddingBottom: -10, paddingRight: 0, width: 75, height: 75)
pinkButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
view.addSubview(flipCameraButton)
view.addSubview(captureButton)
view.addSubview(orangeButton)
view.addSubview(greenButton)
view.addSubview(pinkButton)
}
//MARK: Camera Protocols
func swiftyCamSessionDidStartRunning(_ swiftyCam: SwiftyCamViewController) {
print("Session did start running")
captureButton.buttonEnabled = true
}
func swiftyCamSessionDidStopRunning(_ swiftyCam: SwiftyCamViewController) {
print("Session did stop running")
captureButton.buttonEnabled = false
}
func swiftyCam(_ swiftyCam: SwiftyCamViewController, didTake photo: UIImage) {
let newVC = AfterPhotoTakenView(image: photo)
self.present(newVC, animated: true, completion: nil)
}
func swiftyCam(_ swiftyCam: SwiftyCamViewController, didBeginRecordingVideo camera: SwiftyCamViewController.CameraSelection) {
print("Did Begin Recording")
captureButton.growButton()
hideButtons()
}
func swiftyCam(_ swiftyCam: SwiftyCamViewController, didFinishRecordingVideo camera: SwiftyCamViewController.CameraSelection) {
print("Did finish Recording")
captureButton.shrinkButton()
showButtons()
}
func swiftyCam(_ swiftyCam: SwiftyCamViewController, didFinishProcessVideoAt url: URL) {
let newVC = VideoView(videoURL: url)
self.present(newVC, animated: true, completion: nil)
}
func swiftyCam(_ swiftyCam: SwiftyCamViewController, didFocusAtPoint point: CGPoint) {
print("Did focus at point: \(point)")
focusAnimationAt(point)
}
func swiftyCamDidFailToConfigure(_ swiftyCam: SwiftyCamViewController) {
let message = NSLocalizedString("Unable to capture media", comment: "Alert message when something goes wrong during capture session configuration")
let alertController = UIAlertController(title: "AVCam", message: message, preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: "Alert OK button"), style: .cancel, handler: nil))
present(alertController, animated: true, completion: nil)
}
func swiftyCam(_ swiftyCam: SwiftyCamViewController, didChangeZoomLevel zoom: CGFloat) {
print("Zoom level did change. Level: \(zoom)")
print(zoom)
}
func swiftyCam(_ swiftyCam: SwiftyCamViewController, didSwitchCameras camera: SwiftyCamViewController.CameraSelection) {
print("Camera did change to \(camera.rawValue)")
print(camera)
}
func swiftyCam(_ swiftyCam: SwiftyCamViewController, didFailToRecordVideo error: Error) {
print(error)
}
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
}
extension CameraViewController {
fileprivate func hideButtons() {
UIView.animate(withDuration: 0.25) {
self.flipCameraButton.alpha = 0.0
}
}
fileprivate func showButtons() {
UIView.animate(withDuration: 0.25) {
self.flipCameraButton.alpha = 1.0
}
}
fileprivate func focusAnimationAt(_ point: CGPoint) {
let focusView = UIImageView(image: #imageLiteral(resourceName: "focus"))
focusView.center = point
focusView.alpha = 0.0
view.addSubview(focusView)
UIView.animate(withDuration: 0.25, delay: 0.0, options: .curveEaseInOut, animations: {
focusView.alpha = 1.0
focusView.transform = CGAffineTransform(scaleX: 1.25, y: 1.25)
}) { (success) in
UIView.animate(withDuration: 0.15, delay: 0.5, options: .curveEaseInOut, animations: {
focusView.alpha = 0.0
focusView.transform = CGAffineTransform(translationX: 0.6, y: 0.6)
}) { (success) in
focusView.removeFromSuperview()
}
}
}
fileprivate func toggleFlashAnimation() {
if flashEnabled == true {
//flashButton.setImage(#imageLiteral(resourceName: "flash"), for: UIControlState())
} else {
//flashButton.setImage(#imageLiteral(resourceName: "flashOutline"), for: UIControlState())
}
}
}
这是用户滑动到另一个视图时的样子,按钮没有响应,用户也无法向上或向下滑动这些视图。
这是我试图在用户从左向右滑动或单击粉红色消息按钮时呈现的视图示例。
class MessagesView: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.white
setupNavBar()
navigationController?.isNavigationBarHidden = false
if #available(iOS 11.0, *) {
navigationController?.navigationBar.prefersLargeTitles = true
self.navigationController?.navigationBar.largeTitleTextAttributes = [NSAttributedStringKey.foregroundColor: UIColor.white]
} else {
// Fallback on earlier versions
}
}
override func viewWillAppear(_ animated: Bool) {
if #available(iOS 11.0, *) {
navigationController?.navigationBar.prefersLargeTitles = true
self.navigationController?.navigationBar.largeTitleTextAttributes = [NSAttributedStringKey.foregroundColor: UIColor.white]
setupNavBar()
} else {
setupNavBar()
}
}
func setupNavBar() {
UIApplication.shared.statusBarStyle = .lightContent
self.navigationController?.isNavigationBarHidden = false
self.navigationController?.navigationBar.topItem?.title = "Messages"
self.navigationController?.navigationBar.titleTextAttributes = [NSAttributedStringKey.foregroundColor: UIColor.white]
self.navigationController?.navigationBar.barTintColor = UIColor.pinkNeonColor
self.navigationController?.navigationBar.tintColor = UIColor.white
}
}
public enum Position {
case center
case top
case bottom
case left
case right
}
enum ActivePanDirection {
case undefined
case horizontal
case vertical
}
public protocol SwipeNavigationControllerDelegate: class {
func swipeNavigationController(_ controller: SwipeNavigationController, willShowEmbeddedViewForPosition position: Position)
func swipeNavigationController(_ controller: SwipeNavigationController, didShowEmbeddedViewForPosition position: Position)
}
open class SwipeNavigationController: SwiftyCamViewController, SwiftyCamViewControllerDelegate {
@IBOutlet fileprivate var currentXOffset: NSLayoutConstraint!
@IBOutlet fileprivate var currentYOffset: NSLayoutConstraint!
open fileprivate(set) weak var activeViewController: UIViewController!
public weak var delegate: SwipeNavigationControllerDelegate?
open fileprivate(set) var centerViewController: UIViewController!
open var topViewController: UIViewController? {
willSet(newValue) {
self.shouldShowTopViewController = newValue != nil
guard let viewController = newValue else {
return
}
addEmbeddedViewController(viewController, previousViewController: topViewController, position: .top)
}
}
open var bottomViewController: UIViewController? {
willSet(newValue) {
self.shouldShowBottomViewController = newValue != nil
guard let viewController = newValue else {
return
}
addEmbeddedViewController(viewController, previousViewController: bottomViewController, position: .bottom)
}
}
open var leftViewController: UIViewController? {
willSet(newValue) {
self.shouldShowLeftViewController = newValue != nil
guard let viewController = newValue else {
return
}
addEmbeddedViewController(viewController, previousViewController: leftViewController, position: .left)
}
}
open var rightViewController: UIViewController? {
willSet(newValue) {
self.shouldShowRightViewController = newValue != nil
guard let viewController = newValue else {
return
}
addEmbeddedViewController(viewController, previousViewController: rightViewController, position: .right)
}
}
open override var shouldAutomaticallyForwardAppearanceMethods: Bool {
get {
return false
}
}
@IBOutlet fileprivate var mainPanGesture: UIPanGestureRecognizer!
fileprivate var previousNonZeroDirectionChange = CGVector(dx: 0.0, dy: 0.0)
fileprivate var activePanDirection = ActivePanDirection.undefined
fileprivate let verticalSnapThresholdFraction: CGFloat = 0.15
fileprivate let horizontalSnapThresholdFraction: CGFloat = 0.15
fileprivate var centerContainerOffset: CGVector!
fileprivate var topContainerOffset: CGVector!
fileprivate var bottomContainerOffset: CGVector!
fileprivate var leftContainerOffset: CGVector!
fileprivate var rightContainerOffset: CGVector!
open var shouldShowTopViewController = true
open var shouldShowBottomViewController = true
open var shouldShowLeftViewController = true
open var shouldShowRightViewController = true
open var shouldShowCenterViewController = true
fileprivate let swipeAnimateDuration = 0.2
public init(centerViewController: UIViewController) {
super.init(nibName: nil, bundle: nil)
shouldShowTopViewController = false
shouldShowBottomViewController = false
shouldShowLeftViewController = false
shouldShowRightViewController = false
self.centerViewController = centerViewController
addChildViewController(centerViewController)
centerViewController.didMove(toParentViewController: self)
}
public func swiftyCamSessionDidStartRunning(_ swiftyCam: SwiftyCamViewController) {
print("Session did start running")
captureButton.buttonEnabled = true
}
public func swiftyCamSessionDidStopRunning(_ swiftyCam: SwiftyCamViewController) {
print("Session did stop running")
captureButton.buttonEnabled = false
}
public func swiftyCam(_ swiftyCam: SwiftyCamViewController, didTake photo: UIImage) {
let newVC = PhotoViewController(image: photo)
self.present(newVC, animated: true, completion: nil)
}
public func swiftyCam(_ swiftyCam: SwiftyCamViewController, didBeginRecordingVideo camera: SwiftyCamViewController.CameraSelection) {
print("Did Begin Recording")
captureButton.growButton()
hideButtons()
}
public func swiftyCam(_ swiftyCam: SwiftyCamViewController, didFinishRecordingVideo camera: SwiftyCamViewController.CameraSelection) {
print("Did finish Recording")
captureButton.shrinkButton()
showButtons()
}
public func swiftyCam(_ swiftyCam: SwiftyCamViewController, didFinishProcessVideoAt url: URL) {
let newVC = VideoViewController(videoURL: url)
self.present(newVC, animated: true, completion: nil)
}
public func swiftyCam(_ swiftyCam: SwiftyCamViewController, didFocusAtPoint point: CGPoint) {
print("Did focus at point: \(point)")
focusAnimationAt(point)
}
public func swiftyCamDidFailToConfigure(_ swiftyCam: SwiftyCamViewController) {
let message = NSLocalizedString("Unable to capture media", comment: "Alert message when something goes wrong during capture session configuration")
let alertController = UIAlertController(title: "AVCam", message: message, preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: "Alert OK button"), style: .cancel, handler: nil))
present(alertController, animated: true, completion: nil)
}
public func swiftyCam(_ swiftyCam: SwiftyCamViewController, didChangeZoomLevel zoom: CGFloat) {
print("Zoom level did change. Level: \(zoom)")
print(zoom)
}
public func swiftyCam(_ swiftyCam: SwiftyCamViewController, didSwitchCameras camera: SwiftyCamViewController.CameraSelection) {
print("Camera did change to \(camera.rawValue)")
print(camera)
}
public func swiftyCam(_ swiftyCam: SwiftyCamViewController, didFailToRecordVideo error: Error) {
print(error)
}
public required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
let flipCameraButton: UIButton = {
let button = UIButton()
let image = UIImage(named: "cameraSwitch")
button.setImage(image, for: .normal)
button.addTarget(self, action: #selector(cameraSwitchTapped), for: .touchUpInside)
return button
}()
let captureButton: SwiftyRecordButton = {
let button = SwiftyRecordButton(frame: CGRect(x: 150, y: 572, width: 75, height: 75))
let image = UIImage(named: "focus")
button.setImage(image, for: .normal)
button.addTarget(self, action: #selector(cameraTapped), for: .touchUpInside)
return button
}()
let orangeButton: UIButton = {
let button = UIButton()
let image = UIImage(named: "OrangeIcon")
button.setImage(image, for: .normal)
button.addTarget(self, action: #selector(goToOrange), for: .touchUpInside)
return button
}()
let greenButton: UIButton = {
let button = UIButton()
let image = UIImage(named: "GreenIcon")
button.setImage(image, for: .normal)
button.addTarget(self, action: #selector(goToGreen), for: .touchUpInside)
return button
}()
let pinkButton: UIButton = {
let button = UIButton()
let image = UIImage(named: "pinkCameraIcon")
button.setImage(image, for: .normal)
button.addTarget(self, action: #selector(goToPink), for: .touchUpInside)
return button
}()
@objc func goToOrange() {
//orangeVC.navigationController?.setNavigationBarHidden(false, animated: true)
self.containerSwipeNavigationController?.showEmbeddedView(position: .left)
}
@objc func goToGreen() {
//greenVC.navigationController?.setNavigationBarHidden(false, animated: true)
self.containerSwipeNavigationController?.showEmbeddedView(position: .right)
}
@objc func goToPink() {
self.containerSwipeNavigationController?.showEmbeddedView(position: .bottom)
}
@objc func cameraSwitchTapped() {
switchCamera()
}
@objc func cameraTapped() {
print("CAMERA TAPPED")
takePhoto()
}
// Mark: - Functions
open override func viewDidLoad() {
super.viewDidLoad()
self.cameraDelegate = self
if currentXOffset == nil && currentYOffset == nil {
view.addSubview(centerViewController.view)
centerViewController.view.isHidden = true
centerViewController.view.translatesAutoresizingMaskIntoConstraints = false
self.currentXOffset = alignCenterXConstraint(forItem: centerViewController.view, toItem: view, position: .center)
self.currentYOffset = alignCenterYConstraint(forItem: centerViewController.view, toItem: view, position: .center)
view.addConstraints([self.currentXOffset, self.currentYOffset])
view.addConstraints(sizeConstraints(forItem: centerViewController.view, toItem: view))
}
testViewdid()
assert(currentXOffset != nil && currentYOffset != nil, "both currentXOffset and currentYOffset must be set")
if mainPanGesture == nil {
mainPanGesture = UIPanGestureRecognizer(target: self, action: #selector(onPanGestureTriggered(sender:)))
view.addGestureRecognizer(mainPanGesture)
}
let frameWidth = view.frame.size.width
let frameHeight = view.frame.size.height
centerContainerOffset = CGVector(dx: currentXOffset.constant, dy: currentYOffset.constant)
topContainerOffset = CGVector(dx: centerContainerOffset.dx, dy: centerContainerOffset.dy + frameHeight)
bottomContainerOffset = CGVector(dx: centerContainerOffset.dx, dy: centerContainerOffset.dy - frameHeight)
leftContainerOffset = CGVector(dx: centerContainerOffset.dx + frameWidth, dy: centerContainerOffset.dy)
rightContainerOffset = CGVector(dx: centerContainerOffset.dx - frameWidth, dy: centerContainerOffset.dy)
activeViewController = centerViewController
}
open override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
activeViewController.beginAppearanceTransition(true, animated: animated)
}
open override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
activeViewController.endAppearanceTransition()
captureButton.delegate = self
}
open override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
activeViewController.beginAppearanceTransition(false, animated: animated)
}
open override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
activeViewController.endAppearanceTransition()
}
func testViewdid() {
view.addSubview(flipCameraButton)
view.addSubview(captureButton)
view.addSubview(orangeButton)
view.addSubview(greenButton)
view.addSubview(pinkButton)
shouldPrompToAppSettings = true
cameraDelegate = self
maximumVideoDuration = 10.0
shouldUseDeviceOrientation = true
allowAutoRotate = true
audioEnabled = true
captureButton.buttonEnabled = true
navigationController?.isNavigationBarHidden = true
UIApplication.shared.statusBarStyle = .lightContent
navigationController?.isNavigationBarHidden = true
//setupViews()
}
// Let UIKit handle rotation forwarding calls
open override func shouldAutomaticallyForwardRotationMethods() -> Bool {
return true
}
// MARK: - Containers
open func showEmbeddedView(position: Position) {
weak var disappearingViewController: UIViewController?
let targetOffset: CGVector
switch position {
case .center:
if !activeViewController.isEqual(centerViewController) {
disappearingViewController = activeViewController
}
activeViewController = centerViewController
targetOffset = centerContainerOffset
case .top:
activeViewController = topViewController
targetOffset = topContainerOffset
case .bottom:
activeViewController = bottomViewController
targetOffset = bottomContainerOffset
case .left:
activeViewController = leftViewController
targetOffset = leftContainerOffset
case .right:
activeViewController = rightViewController
targetOffset = rightContainerOffset
}
if !activeViewController.isEqual(centerViewController) {
disappearingViewController = centerViewController
}
currentXOffset.constant = targetOffset.dx
currentYOffset.constant = targetOffset.dy
disappearingViewController?.beginAppearanceTransition(false, animated: true)
activeViewController.beginAppearanceTransition(true, animated: true)
delegate?.swipeNavigationController(self, willShowEmbeddedViewForPosition: position)
UIView.animate(withDuration: swipeAnimateDuration, animations: {
self.view.layoutIfNeeded()
}) { (finished) in
self.delegate?.swipeNavigationController(self, didShowEmbeddedViewForPosition: position)
self.activeViewController.endAppearanceTransition()
disappearingViewController?.endAppearanceTransition()
}
}
open func isContainerActive(position: Position) -> Bool {
let targetOffset: CGVector
switch position {
case .center:
targetOffset = centerContainerOffset
case .top:
targetOffset = topContainerOffset
case .bottom:
targetOffset = bottomContainerOffset
case .left:
targetOffset = leftContainerOffset
case .right:
targetOffset = rightContainerOffset
}
return (currentXOffset.constant, currentYOffset.constant) == (targetOffset.dx, targetOffset.dy)
}
open func lock() {
self.mainPanGesture.isEnabled = false
}
open func unlock() {
self.mainPanGesture.isEnabled = true
}
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
return true
}
@IBAction fileprivate func onPanGestureTriggered(sender: UIPanGestureRecognizer) {
switch sender.state {
case .began:
if isContainerActive(position: .top) || isContainerActive(position: .bottom) {
activePanDirection = .vertical
} else if isContainerActive(position: .left) || isContainerActive(position: .right) {
activePanDirection = .horizontal
} else {
activePanDirection = .undefined
}
case .changed:
let translationInMainView = sender.translation(in: view)
if translationInMainView.x != 0 {
previousNonZeroDirectionChange.dx = translationInMainView.x
}
if translationInMainView.y != 0 {
previousNonZeroDirectionChange.dy = translationInMainView.y
}
switch activePanDirection {
case .undefined:
activePanDirection = fabs(translationInMainView.x) > fabs(translationInMainView.y) ? .horizontal : .vertical
case .horizontal:
let isCurrentlyShowingRightViewController = currentXOffset.constant < centerContainerOffset.dx
let isCurrentlyShowingLeftViewController = currentXOffset.constant > centerContainerOffset.dx
let minX = isCurrentlyShowingRightViewController || shouldShowRightViewController ? rightContainerOffset.dx : centerContainerOffset.dx
let maxX = isCurrentlyShowingLeftViewController || shouldShowLeftViewController ? leftContainerOffset.dx : centerContainerOffset.dx
if shouldShowCenterViewController {
currentXOffset.constant = min(max(minX, currentXOffset.constant + translationInMainView.x), maxX)
}
case .vertical:
let isCurrentlyShowingBottomViewController = currentYOffset.constant < centerContainerOffset.dy
let isCurrentlyShowingTopViewController = currentYOffset.constant > centerContainerOffset.dy
let minY = isCurrentlyShowingBottomViewController || shouldShowBottomViewController ? bottomContainerOffset.dy : centerContainerOffset.dy
let maxY = isCurrentlyShowingTopViewController || shouldShowTopViewController ? topContainerOffset.dy : centerContainerOffset.dy
if shouldShowCenterViewController {
currentYOffset.constant = min(max(minY, currentYOffset.constant + translationInMainView.y), maxY)
}
}
// reset translation for next iteration
sender.setTranslation(CGPoint.zero, in: view)
case .ended:
/*
* Handle snapping here
*/
switch activePanDirection {
case .horizontal:
if currentXOffset.constant > 0.0 {
// within range of center container
if currentXOffset.constant < (horizontalSnapThresholdFraction * view.frame.size.width) {
showEmbeddedView(position: .center)
}
// within range of left container
else if currentXOffset.constant > ((1.0 - horizontalSnapThresholdFraction) * view.frame.size.width) {
showEmbeddedView(position: .left)
}
// center region: depends on inertia direction
else {
// pulled right
if previousNonZeroDirectionChange.dx > 0.0 {
showEmbeddedView(position: .left)
}
// pulled left
else {
showEmbeddedView(position: .center)
}
}
}
else if currentXOffset.constant < 0.0 {
// within range of center container
if currentXOffset.constant > (horizontalSnapThresholdFraction * -view.frame.size.width) {
showEmbeddedView(position: .center)
}
// within range of right container
else if currentXOffset.constant < ((1.0 - horizontalSnapThresholdFraction) * -view.frame.size.width) {
showEmbeddedView(position: .right)
}
// center region: depends on inertia direction
else {
// pulled left
if previousNonZeroDirectionChange.dx < 0.0 {
showEmbeddedView(position: .right)
}
// pulled right
else {
showEmbeddedView(position: .center)
}
}
}
case .vertical:
if currentYOffset.constant > 0.0 {
if currentYOffset.constant < (verticalSnapThresholdFraction * view.frame.size.height) {
showEmbeddedView(position: .center)
}
else if currentYOffset.constant > ((1.0 - verticalSnapThresholdFraction) * view.frame.size.height) {
showEmbeddedView(position: .top)
}
else {
if previousNonZeroDirectionChange.dy > 0.0 {
showEmbeddedView(position: .top)
}
else {
showEmbeddedView(position: .center)
}
}
}
else if currentYOffset.constant < 0.0 {
if currentYOffset.constant > (verticalSnapThresholdFraction * -view.frame.size.height) {
showEmbeddedView(position: .center)
}
else if currentYOffset.constant < ((1.0 - verticalSnapThresholdFraction) * -view.frame.size.height) {
showEmbeddedView(position: .bottom)
}
else {
if previousNonZeroDirectionChange.dy < 0.0 {
showEmbeddedView(position: .bottom)
}
else {
showEmbeddedView(position: .center)
}
}
}
case .undefined:
break
}
default:
break
}
}
func addEmbeddedViewController(_ viewController: UIViewController, previousViewController: UIViewController?, position: Position) {
if viewController.isEqual(previousViewController) {
return
}
previousViewController?.beginAppearanceTransition(false, animated: false)
previousViewController?.view.removeFromSuperview()
previousViewController?.endAppearanceTransition()
previousViewController?.willMove(toParentViewController: nil)
previousViewController?.removeFromParentViewController()
addChildViewController(viewController)
view.addSubview(viewController.view)
view.sendSubview(toBack: viewController.view)
viewController.view.translatesAutoresizingMaskIntoConstraints = false
viewController.didMove(toParentViewController: self)
view.addConstraint(alignCenterXConstraint(forItem: viewController.view, toItem: centerViewController.view, position: position))
view.addConstraint(alignCenterYConstraint(forItem: viewController.view, toItem: centerViewController.view, position: position))
view.addConstraints(sizeConstraints(forItem: viewController.view, toItem: centerViewController.view))
}
func alignCenterXConstraint(forItem item: UIView, toItem: UIView, position: Position) -> NSLayoutConstraint {
let offset = position == .left ? -self.view.frame.width : position == .right ? toItem.frame.width : 0
return NSLayoutConstraint(item: item, attribute: .centerX, relatedBy: .equal, toItem: toItem, attribute: .centerX, multiplier: 1, constant: offset)
}
func alignCenterYConstraint(forItem item: UIView, toItem: UIView, position: Position) -> NSLayoutConstraint {
let offset = position == .top ? -self.view.frame.height : position == .bottom ? toItem.frame.height : 0
return NSLayoutConstraint(item: item, attribute: .centerY, relatedBy: .equal, toItem: toItem, attribute: .centerY, multiplier: 1, constant: offset)
}
func sizeConstraints(forItem item: UIView, toItem: UIView) -> [NSLayoutConstraint] {
let widthConstraint = NSLayoutConstraint(item: item, attribute: .width, relatedBy: .equal, toItem: toItem, attribute: .width, multiplier: 1, constant: 0)
let heightConstraint = NSLayoutConstraint(item: item, attribute: .height, relatedBy: .equal, toItem: toItem, attribute: .height, multiplier: 1, constant: 0)
return [widthConstraint, heightConstraint]
}
func hideButtons() {
UIView.animate(withDuration: 0.25) {
self.flipCameraButton.alpha = 0.0
}
}
func showButtons() {
UIView.animate(withDuration: 0.25) {
self.flipCameraButton.alpha = 1.0
}
}
func focusAnimationAt(_ point: CGPoint) {
let focusView = UIImageView(image: #imageLiteral(resourceName: "focus"))
focusView.center = point
focusView.alpha = 0.0
view.addSubview(focusView)
UIView.animate(withDuration: 0.25, delay: 0.0, options: .curveEaseInOut, animations: {
focusView.alpha = 1.0
focusView.transform = CGAffineTransform(scaleX: 1.25, y: 1.25)
}) { (success) in
UIView.animate(withDuration: 0.15, delay: 0.5, options: .curveEaseInOut, animations: {
focusView.alpha = 0.0
focusView.transform = CGAffineTransform(translationX: 0.6, y: 0.6)
}) { (success) in
focusView.removeFromSuperview()
}
}
}
func toggleFlashAnimation() {
if flashEnabled == true {
//flashButton.setImage(#imageLiteral(resourceName: "flash"), for: UIControlState())
} else {
//flashButton.setImage(#imageLiteral(resourceName: "flashOutline"), for: UIControlState())
}
}
}
CameraViewControler -
class CameraViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
UIApplication.shared.statusBarStyle = .lightContent
navigationController?.isNavigationBarHidden = true
}
}
我已经按照 SwiftyCam Everything lays out correctly and is going well; however, when the camera button is pushed I get a message in the console saying "[SwiftyCam]: Cannot take photo. Capture session is not running". There have been other people having this problem with swift 4 and you can find that here. I have gone through the whole framework line by line but for some reason I can't figure it out. I would really appreciate it if someone could look at the framework and the documentation and help me out. The way I'm doing it is just about exactly how it's done in the Swift 4 demo project 上 GitHub 上的演示项目创建了我的相机视图,因此这将是代码参考。
提前致谢
编辑:下面是在 WelcomeVC
之后设置 SwipeNavigationController 时的代码let swipeNavigationController = SwipeNavigationController(centerViewController: CameraViewController())
swipeNavigationController.topViewController = BlueView()
swipeNavigationController.bottomViewController = PinkView()
swipeNavigationController.leftViewController = OrangeView()
swipeNavigationController.rightViewController = GreenView()
cameraView.navigationController?.setNavigationBarHidden(true, animated: false)
orangeView.navigationController?.setNavigationBarHidden(false, animated: false)
greenView.navigationController?.setNavigationBarHidden(false, animated: false)
let navController = UINavigationController(rootViewController: swipeNavigationController)
self.present(navController, animated: true, completion: nil)
CameraVC中的全部代码如下
class CameraViewController: SwiftyCamViewController, SwiftyCamViewControllerDelegate, SwipeNavigationControllerDelegate {
let orangeVC = OrangeView()
let greenVC = GreenView()
let blueVC = BlueView()
let pinkVC = PinkView()
let flipCameraButton: UIButton = {
let button = UIButton()
let image = UIImage(named: "cameraSwitch")
button.setImage(image, for: .normal)
button.addTarget(self, action: #selector(cameraSwitchTapped), for: .touchUpInside)
return button
}()
let captureButton: SwiftyRecordButton = {
let button = SwiftyRecordButton(frame: CGRect(x: 150, y: 572, width: 75, height: 75))
//let image = UIImage(named: "focus")
//button.setImage(image, for: .normal)
//button.addTarget(self, action: #selector(cameraTapped), for: .touchUpInside)
return button
}()
let orangeButton: UIButton = {
let button = UIButton()
let image = UIImage(named: "OrangeIcon")
button.setImage(image, for: .normal)
button.addTarget(self, action: #selector(goToOrange), for: .touchUpInside)
return button
}()
let greenButton: UIButton = {
let button = UIButton()
let image = UIImage(named: "GreenIcon")
button.setImage(image, for: .normal)
button.addTarget(self, action: #selector(goToGreen), for: .touchUpInside)
return button
}()
let pinkButton: UIButton = {
let button = UIButton()
let image = UIImage(named: "pinkCameraIcon")
button.setImage(image, for: .normal)
button.addTarget(self, action: #selector(goToPink), for: .touchUpInside)
return button
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(flipCameraButton)
view.addSubview(captureButton)
view.addSubview(orangeButton)
view.addSubview(greenButton)
view.addSubview(pinkButton)
shouldPrompToAppSettings = true
cameraDelegate = self
maximumVideoDuration = 10.0
shouldUseDeviceOrientation = true
allowAutoRotate = true
audioEnabled = true
// disable capture button until session starts
captureButton.buttonEnabled = false
navigationController?.isNavigationBarHidden = true
UIApplication.shared.statusBarStyle = .lightContent
navigationController?.isNavigationBarHidden = true
setupViews()
}
override func viewWillAppear(_ animated: Bool) {
UIApplication.shared.statusBarStyle = .lightContent
navigationController?.isNavigationBarHidden = true
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
captureButton.delegate = self
}
//
@objc func goToOrange() {
orangeVC.navigationController?.setNavigationBarHidden(false, animated: true)
self.containerSwipeNavigationController?.showEmbeddedView(position: .left)
}
@objc func goToGreen() {
greenVC.navigationController?.setNavigationBarHidden(false, animated: true)
self.containerSwipeNavigationController?.showEmbeddedView(position: .right)
}
@objc func goToPink() {
self.containerSwipeNavigationController?.showEmbeddedView(position: .bottom)
}
@objc func cameraSwitchTapped() {
switchCamera()
}
@objc func cameraTapped() {
print("CAMERA TAPPED")
takePhoto()
}
func setupViews() {
flipCameraButton.anchor(top: view.topAnchor, left: nil, bottom: nil, right: view.rightAnchor, paddingTop: 25, paddingLeft: 0, paddingBottom: 0, paddingRight: 12, width: 35, height: 35)
captureButton.anchor(top: nil, left: nil, bottom: pinkButton.topAnchor, right: nil, paddingTop: 0, paddingLeft: 0, paddingBottom: 10, paddingRight: 0, width: 75, height: 75)
captureButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
orangeButton.anchor(top: nil, left: view.leftAnchor, bottom: view.bottomAnchor, right: nil, paddingTop: 0, paddingLeft: 10, paddingBottom: 0, paddingRight: 0, width: 75, height: 75)
greenButton.anchor(top: nil, left: nil, bottom: view.bottomAnchor, right: view.rightAnchor, paddingTop: 0, paddingLeft: 0, paddingBottom: 0, paddingRight: 10, width: 75, height: 75)
pinkButton.anchor(top: nil, left: nil, bottom: view.bottomAnchor, right: nil, paddingTop: 0, paddingLeft: 0, paddingBottom: -10, paddingRight: 0, width: 75, height: 75)
pinkButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
view.addSubview(flipCameraButton)
view.addSubview(captureButton)
view.addSubview(orangeButton)
view.addSubview(greenButton)
view.addSubview(pinkButton)
}
//MARK: Camera Protocols
func swiftyCamSessionDidStartRunning(_ swiftyCam: SwiftyCamViewController) {
print("Session did start running")
captureButton.buttonEnabled = true
}
func swiftyCamSessionDidStopRunning(_ swiftyCam: SwiftyCamViewController) {
print("Session did stop running")
captureButton.buttonEnabled = false
}
func swiftyCam(_ swiftyCam: SwiftyCamViewController, didTake photo: UIImage) {
let newVC = AfterPhotoTakenView(image: photo)
self.present(newVC, animated: true, completion: nil)
}
func swiftyCam(_ swiftyCam: SwiftyCamViewController, didBeginRecordingVideo camera: SwiftyCamViewController.CameraSelection) {
print("Did Begin Recording")
captureButton.growButton()
hideButtons()
}
func swiftyCam(_ swiftyCam: SwiftyCamViewController, didFinishRecordingVideo camera: SwiftyCamViewController.CameraSelection) {
print("Did finish Recording")
captureButton.shrinkButton()
showButtons()
}
func swiftyCam(_ swiftyCam: SwiftyCamViewController, didFinishProcessVideoAt url: URL) {
let newVC = VideoView(videoURL: url)
self.present(newVC, animated: true, completion: nil)
}
func swiftyCam(_ swiftyCam: SwiftyCamViewController, didFocusAtPoint point: CGPoint) {
print("Did focus at point: \(point)")
focusAnimationAt(point)
}
func swiftyCamDidFailToConfigure(_ swiftyCam: SwiftyCamViewController) {
let message = NSLocalizedString("Unable to capture media", comment: "Alert message when something goes wrong during capture session configuration")
let alertController = UIAlertController(title: "AVCam", message: message, preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: "Alert OK button"), style: .cancel, handler: nil))
present(alertController, animated: true, completion: nil)
}
func swiftyCam(_ swiftyCam: SwiftyCamViewController, didChangeZoomLevel zoom: CGFloat) {
print("Zoom level did change. Level: \(zoom)")
print(zoom)
}
func swiftyCam(_ swiftyCam: SwiftyCamViewController, didSwitchCameras camera: SwiftyCamViewController.CameraSelection) {
print("Camera did change to \(camera.rawValue)")
print(camera)
}
func swiftyCam(_ swiftyCam: SwiftyCamViewController, didFailToRecordVideo error: Error) {
print(error)
}
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
}
extension CameraViewController {
fileprivate func hideButtons() {
UIView.animate(withDuration: 0.25) {
self.flipCameraButton.alpha = 0.0
}
}
fileprivate func showButtons() {
UIView.animate(withDuration: 0.25) {
self.flipCameraButton.alpha = 1.0
}
}
fileprivate func focusAnimationAt(_ point: CGPoint) {
let focusView = UIImageView(image: #imageLiteral(resourceName: "focus"))
focusView.center = point
focusView.alpha = 0.0
view.addSubview(focusView)
UIView.animate(withDuration: 0.25, delay: 0.0, options: .curveEaseInOut, animations: {
focusView.alpha = 1.0
focusView.transform = CGAffineTransform(scaleX: 1.25, y: 1.25)
}) { (success) in
UIView.animate(withDuration: 0.15, delay: 0.5, options: .curveEaseInOut, animations: {
focusView.alpha = 0.0
focusView.transform = CGAffineTransform(translationX: 0.6, y: 0.6)
}) { (success) in
focusView.removeFromSuperview()
}
}
}
fileprivate func toggleFlashAnimation() {
if flashEnabled == true {
//flashButton.setImage(#imageLiteral(resourceName: "flash"), for: UIControlState())
} else {
//flashButton.setImage(#imageLiteral(resourceName: "flashOutline"), for: UIControlState())
}
}
}
这是用户滑动到另一个视图时的样子,按钮没有响应,用户也无法向上或向下滑动这些视图。
这是我试图在用户从左向右滑动或单击粉红色消息按钮时呈现的视图示例。
class MessagesView: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.white
setupNavBar()
navigationController?.isNavigationBarHidden = false
if #available(iOS 11.0, *) {
navigationController?.navigationBar.prefersLargeTitles = true
self.navigationController?.navigationBar.largeTitleTextAttributes = [NSAttributedStringKey.foregroundColor: UIColor.white]
} else {
// Fallback on earlier versions
}
}
override func viewWillAppear(_ animated: Bool) {
if #available(iOS 11.0, *) {
navigationController?.navigationBar.prefersLargeTitles = true
self.navigationController?.navigationBar.largeTitleTextAttributes = [NSAttributedStringKey.foregroundColor: UIColor.white]
setupNavBar()
} else {
setupNavBar()
}
}
func setupNavBar() {
UIApplication.shared.statusBarStyle = .lightContent
self.navigationController?.isNavigationBarHidden = false
self.navigationController?.navigationBar.topItem?.title = "Messages"
self.navigationController?.navigationBar.titleTextAttributes = [NSAttributedStringKey.foregroundColor: UIColor.white]
self.navigationController?.navigationBar.barTintColor = UIColor.pinkNeonColor
self.navigationController?.navigationBar.tintColor = UIColor.white
}
}
public enum Position {
case center
case top
case bottom
case left
case right
}
enum ActivePanDirection {
case undefined
case horizontal
case vertical
}
public protocol SwipeNavigationControllerDelegate: class {
func swipeNavigationController(_ controller: SwipeNavigationController, willShowEmbeddedViewForPosition position: Position)
func swipeNavigationController(_ controller: SwipeNavigationController, didShowEmbeddedViewForPosition position: Position)
}
open class SwipeNavigationController: SwiftyCamViewController, SwiftyCamViewControllerDelegate {
@IBOutlet fileprivate var currentXOffset: NSLayoutConstraint!
@IBOutlet fileprivate var currentYOffset: NSLayoutConstraint!
open fileprivate(set) weak var activeViewController: UIViewController!
public weak var delegate: SwipeNavigationControllerDelegate?
open fileprivate(set) var centerViewController: UIViewController!
open var topViewController: UIViewController? {
willSet(newValue) {
self.shouldShowTopViewController = newValue != nil
guard let viewController = newValue else {
return
}
addEmbeddedViewController(viewController, previousViewController: topViewController, position: .top)
}
}
open var bottomViewController: UIViewController? {
willSet(newValue) {
self.shouldShowBottomViewController = newValue != nil
guard let viewController = newValue else {
return
}
addEmbeddedViewController(viewController, previousViewController: bottomViewController, position: .bottom)
}
}
open var leftViewController: UIViewController? {
willSet(newValue) {
self.shouldShowLeftViewController = newValue != nil
guard let viewController = newValue else {
return
}
addEmbeddedViewController(viewController, previousViewController: leftViewController, position: .left)
}
}
open var rightViewController: UIViewController? {
willSet(newValue) {
self.shouldShowRightViewController = newValue != nil
guard let viewController = newValue else {
return
}
addEmbeddedViewController(viewController, previousViewController: rightViewController, position: .right)
}
}
open override var shouldAutomaticallyForwardAppearanceMethods: Bool {
get {
return false
}
}
@IBOutlet fileprivate var mainPanGesture: UIPanGestureRecognizer!
fileprivate var previousNonZeroDirectionChange = CGVector(dx: 0.0, dy: 0.0)
fileprivate var activePanDirection = ActivePanDirection.undefined
fileprivate let verticalSnapThresholdFraction: CGFloat = 0.15
fileprivate let horizontalSnapThresholdFraction: CGFloat = 0.15
fileprivate var centerContainerOffset: CGVector!
fileprivate var topContainerOffset: CGVector!
fileprivate var bottomContainerOffset: CGVector!
fileprivate var leftContainerOffset: CGVector!
fileprivate var rightContainerOffset: CGVector!
open var shouldShowTopViewController = true
open var shouldShowBottomViewController = true
open var shouldShowLeftViewController = true
open var shouldShowRightViewController = true
open var shouldShowCenterViewController = true
fileprivate let swipeAnimateDuration = 0.2
public init(centerViewController: UIViewController) {
super.init(nibName: nil, bundle: nil)
shouldShowTopViewController = false
shouldShowBottomViewController = false
shouldShowLeftViewController = false
shouldShowRightViewController = false
self.centerViewController = centerViewController
addChildViewController(centerViewController)
centerViewController.didMove(toParentViewController: self)
}
public func swiftyCamSessionDidStartRunning(_ swiftyCam: SwiftyCamViewController) {
print("Session did start running")
captureButton.buttonEnabled = true
}
public func swiftyCamSessionDidStopRunning(_ swiftyCam: SwiftyCamViewController) {
print("Session did stop running")
captureButton.buttonEnabled = false
}
public func swiftyCam(_ swiftyCam: SwiftyCamViewController, didTake photo: UIImage) {
let newVC = PhotoViewController(image: photo)
self.present(newVC, animated: true, completion: nil)
}
public func swiftyCam(_ swiftyCam: SwiftyCamViewController, didBeginRecordingVideo camera: SwiftyCamViewController.CameraSelection) {
print("Did Begin Recording")
captureButton.growButton()
hideButtons()
}
public func swiftyCam(_ swiftyCam: SwiftyCamViewController, didFinishRecordingVideo camera: SwiftyCamViewController.CameraSelection) {
print("Did finish Recording")
captureButton.shrinkButton()
showButtons()
}
public func swiftyCam(_ swiftyCam: SwiftyCamViewController, didFinishProcessVideoAt url: URL) {
let newVC = VideoViewController(videoURL: url)
self.present(newVC, animated: true, completion: nil)
}
public func swiftyCam(_ swiftyCam: SwiftyCamViewController, didFocusAtPoint point: CGPoint) {
print("Did focus at point: \(point)")
focusAnimationAt(point)
}
public func swiftyCamDidFailToConfigure(_ swiftyCam: SwiftyCamViewController) {
let message = NSLocalizedString("Unable to capture media", comment: "Alert message when something goes wrong during capture session configuration")
let alertController = UIAlertController(title: "AVCam", message: message, preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: "Alert OK button"), style: .cancel, handler: nil))
present(alertController, animated: true, completion: nil)
}
public func swiftyCam(_ swiftyCam: SwiftyCamViewController, didChangeZoomLevel zoom: CGFloat) {
print("Zoom level did change. Level: \(zoom)")
print(zoom)
}
public func swiftyCam(_ swiftyCam: SwiftyCamViewController, didSwitchCameras camera: SwiftyCamViewController.CameraSelection) {
print("Camera did change to \(camera.rawValue)")
print(camera)
}
public func swiftyCam(_ swiftyCam: SwiftyCamViewController, didFailToRecordVideo error: Error) {
print(error)
}
public required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
let flipCameraButton: UIButton = {
let button = UIButton()
let image = UIImage(named: "cameraSwitch")
button.setImage(image, for: .normal)
button.addTarget(self, action: #selector(cameraSwitchTapped), for: .touchUpInside)
return button
}()
let captureButton: SwiftyRecordButton = {
let button = SwiftyRecordButton(frame: CGRect(x: 150, y: 572, width: 75, height: 75))
let image = UIImage(named: "focus")
button.setImage(image, for: .normal)
button.addTarget(self, action: #selector(cameraTapped), for: .touchUpInside)
return button
}()
let orangeButton: UIButton = {
let button = UIButton()
let image = UIImage(named: "OrangeIcon")
button.setImage(image, for: .normal)
button.addTarget(self, action: #selector(goToOrange), for: .touchUpInside)
return button
}()
let greenButton: UIButton = {
let button = UIButton()
let image = UIImage(named: "GreenIcon")
button.setImage(image, for: .normal)
button.addTarget(self, action: #selector(goToGreen), for: .touchUpInside)
return button
}()
let pinkButton: UIButton = {
let button = UIButton()
let image = UIImage(named: "pinkCameraIcon")
button.setImage(image, for: .normal)
button.addTarget(self, action: #selector(goToPink), for: .touchUpInside)
return button
}()
@objc func goToOrange() {
//orangeVC.navigationController?.setNavigationBarHidden(false, animated: true)
self.containerSwipeNavigationController?.showEmbeddedView(position: .left)
}
@objc func goToGreen() {
//greenVC.navigationController?.setNavigationBarHidden(false, animated: true)
self.containerSwipeNavigationController?.showEmbeddedView(position: .right)
}
@objc func goToPink() {
self.containerSwipeNavigationController?.showEmbeddedView(position: .bottom)
}
@objc func cameraSwitchTapped() {
switchCamera()
}
@objc func cameraTapped() {
print("CAMERA TAPPED")
takePhoto()
}
// Mark: - Functions
open override func viewDidLoad() {
super.viewDidLoad()
self.cameraDelegate = self
if currentXOffset == nil && currentYOffset == nil {
view.addSubview(centerViewController.view)
centerViewController.view.isHidden = true
centerViewController.view.translatesAutoresizingMaskIntoConstraints = false
self.currentXOffset = alignCenterXConstraint(forItem: centerViewController.view, toItem: view, position: .center)
self.currentYOffset = alignCenterYConstraint(forItem: centerViewController.view, toItem: view, position: .center)
view.addConstraints([self.currentXOffset, self.currentYOffset])
view.addConstraints(sizeConstraints(forItem: centerViewController.view, toItem: view))
}
testViewdid()
assert(currentXOffset != nil && currentYOffset != nil, "both currentXOffset and currentYOffset must be set")
if mainPanGesture == nil {
mainPanGesture = UIPanGestureRecognizer(target: self, action: #selector(onPanGestureTriggered(sender:)))
view.addGestureRecognizer(mainPanGesture)
}
let frameWidth = view.frame.size.width
let frameHeight = view.frame.size.height
centerContainerOffset = CGVector(dx: currentXOffset.constant, dy: currentYOffset.constant)
topContainerOffset = CGVector(dx: centerContainerOffset.dx, dy: centerContainerOffset.dy + frameHeight)
bottomContainerOffset = CGVector(dx: centerContainerOffset.dx, dy: centerContainerOffset.dy - frameHeight)
leftContainerOffset = CGVector(dx: centerContainerOffset.dx + frameWidth, dy: centerContainerOffset.dy)
rightContainerOffset = CGVector(dx: centerContainerOffset.dx - frameWidth, dy: centerContainerOffset.dy)
activeViewController = centerViewController
}
open override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
activeViewController.beginAppearanceTransition(true, animated: animated)
}
open override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
activeViewController.endAppearanceTransition()
captureButton.delegate = self
}
open override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
activeViewController.beginAppearanceTransition(false, animated: animated)
}
open override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
activeViewController.endAppearanceTransition()
}
func testViewdid() {
view.addSubview(flipCameraButton)
view.addSubview(captureButton)
view.addSubview(orangeButton)
view.addSubview(greenButton)
view.addSubview(pinkButton)
shouldPrompToAppSettings = true
cameraDelegate = self
maximumVideoDuration = 10.0
shouldUseDeviceOrientation = true
allowAutoRotate = true
audioEnabled = true
captureButton.buttonEnabled = true
navigationController?.isNavigationBarHidden = true
UIApplication.shared.statusBarStyle = .lightContent
navigationController?.isNavigationBarHidden = true
//setupViews()
}
// Let UIKit handle rotation forwarding calls
open override func shouldAutomaticallyForwardRotationMethods() -> Bool {
return true
}
// MARK: - Containers
open func showEmbeddedView(position: Position) {
weak var disappearingViewController: UIViewController?
let targetOffset: CGVector
switch position {
case .center:
if !activeViewController.isEqual(centerViewController) {
disappearingViewController = activeViewController
}
activeViewController = centerViewController
targetOffset = centerContainerOffset
case .top:
activeViewController = topViewController
targetOffset = topContainerOffset
case .bottom:
activeViewController = bottomViewController
targetOffset = bottomContainerOffset
case .left:
activeViewController = leftViewController
targetOffset = leftContainerOffset
case .right:
activeViewController = rightViewController
targetOffset = rightContainerOffset
}
if !activeViewController.isEqual(centerViewController) {
disappearingViewController = centerViewController
}
currentXOffset.constant = targetOffset.dx
currentYOffset.constant = targetOffset.dy
disappearingViewController?.beginAppearanceTransition(false, animated: true)
activeViewController.beginAppearanceTransition(true, animated: true)
delegate?.swipeNavigationController(self, willShowEmbeddedViewForPosition: position)
UIView.animate(withDuration: swipeAnimateDuration, animations: {
self.view.layoutIfNeeded()
}) { (finished) in
self.delegate?.swipeNavigationController(self, didShowEmbeddedViewForPosition: position)
self.activeViewController.endAppearanceTransition()
disappearingViewController?.endAppearanceTransition()
}
}
open func isContainerActive(position: Position) -> Bool {
let targetOffset: CGVector
switch position {
case .center:
targetOffset = centerContainerOffset
case .top:
targetOffset = topContainerOffset
case .bottom:
targetOffset = bottomContainerOffset
case .left:
targetOffset = leftContainerOffset
case .right:
targetOffset = rightContainerOffset
}
return (currentXOffset.constant, currentYOffset.constant) == (targetOffset.dx, targetOffset.dy)
}
open func lock() {
self.mainPanGesture.isEnabled = false
}
open func unlock() {
self.mainPanGesture.isEnabled = true
}
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
return true
}
@IBAction fileprivate func onPanGestureTriggered(sender: UIPanGestureRecognizer) {
switch sender.state {
case .began:
if isContainerActive(position: .top) || isContainerActive(position: .bottom) {
activePanDirection = .vertical
} else if isContainerActive(position: .left) || isContainerActive(position: .right) {
activePanDirection = .horizontal
} else {
activePanDirection = .undefined
}
case .changed:
let translationInMainView = sender.translation(in: view)
if translationInMainView.x != 0 {
previousNonZeroDirectionChange.dx = translationInMainView.x
}
if translationInMainView.y != 0 {
previousNonZeroDirectionChange.dy = translationInMainView.y
}
switch activePanDirection {
case .undefined:
activePanDirection = fabs(translationInMainView.x) > fabs(translationInMainView.y) ? .horizontal : .vertical
case .horizontal:
let isCurrentlyShowingRightViewController = currentXOffset.constant < centerContainerOffset.dx
let isCurrentlyShowingLeftViewController = currentXOffset.constant > centerContainerOffset.dx
let minX = isCurrentlyShowingRightViewController || shouldShowRightViewController ? rightContainerOffset.dx : centerContainerOffset.dx
let maxX = isCurrentlyShowingLeftViewController || shouldShowLeftViewController ? leftContainerOffset.dx : centerContainerOffset.dx
if shouldShowCenterViewController {
currentXOffset.constant = min(max(minX, currentXOffset.constant + translationInMainView.x), maxX)
}
case .vertical:
let isCurrentlyShowingBottomViewController = currentYOffset.constant < centerContainerOffset.dy
let isCurrentlyShowingTopViewController = currentYOffset.constant > centerContainerOffset.dy
let minY = isCurrentlyShowingBottomViewController || shouldShowBottomViewController ? bottomContainerOffset.dy : centerContainerOffset.dy
let maxY = isCurrentlyShowingTopViewController || shouldShowTopViewController ? topContainerOffset.dy : centerContainerOffset.dy
if shouldShowCenterViewController {
currentYOffset.constant = min(max(minY, currentYOffset.constant + translationInMainView.y), maxY)
}
}
// reset translation for next iteration
sender.setTranslation(CGPoint.zero, in: view)
case .ended:
/*
* Handle snapping here
*/
switch activePanDirection {
case .horizontal:
if currentXOffset.constant > 0.0 {
// within range of center container
if currentXOffset.constant < (horizontalSnapThresholdFraction * view.frame.size.width) {
showEmbeddedView(position: .center)
}
// within range of left container
else if currentXOffset.constant > ((1.0 - horizontalSnapThresholdFraction) * view.frame.size.width) {
showEmbeddedView(position: .left)
}
// center region: depends on inertia direction
else {
// pulled right
if previousNonZeroDirectionChange.dx > 0.0 {
showEmbeddedView(position: .left)
}
// pulled left
else {
showEmbeddedView(position: .center)
}
}
}
else if currentXOffset.constant < 0.0 {
// within range of center container
if currentXOffset.constant > (horizontalSnapThresholdFraction * -view.frame.size.width) {
showEmbeddedView(position: .center)
}
// within range of right container
else if currentXOffset.constant < ((1.0 - horizontalSnapThresholdFraction) * -view.frame.size.width) {
showEmbeddedView(position: .right)
}
// center region: depends on inertia direction
else {
// pulled left
if previousNonZeroDirectionChange.dx < 0.0 {
showEmbeddedView(position: .right)
}
// pulled right
else {
showEmbeddedView(position: .center)
}
}
}
case .vertical:
if currentYOffset.constant > 0.0 {
if currentYOffset.constant < (verticalSnapThresholdFraction * view.frame.size.height) {
showEmbeddedView(position: .center)
}
else if currentYOffset.constant > ((1.0 - verticalSnapThresholdFraction) * view.frame.size.height) {
showEmbeddedView(position: .top)
}
else {
if previousNonZeroDirectionChange.dy > 0.0 {
showEmbeddedView(position: .top)
}
else {
showEmbeddedView(position: .center)
}
}
}
else if currentYOffset.constant < 0.0 {
if currentYOffset.constant > (verticalSnapThresholdFraction * -view.frame.size.height) {
showEmbeddedView(position: .center)
}
else if currentYOffset.constant < ((1.0 - verticalSnapThresholdFraction) * -view.frame.size.height) {
showEmbeddedView(position: .bottom)
}
else {
if previousNonZeroDirectionChange.dy < 0.0 {
showEmbeddedView(position: .bottom)
}
else {
showEmbeddedView(position: .center)
}
}
}
case .undefined:
break
}
default:
break
}
}
func addEmbeddedViewController(_ viewController: UIViewController, previousViewController: UIViewController?, position: Position) {
if viewController.isEqual(previousViewController) {
return
}
previousViewController?.beginAppearanceTransition(false, animated: false)
previousViewController?.view.removeFromSuperview()
previousViewController?.endAppearanceTransition()
previousViewController?.willMove(toParentViewController: nil)
previousViewController?.removeFromParentViewController()
addChildViewController(viewController)
view.addSubview(viewController.view)
view.sendSubview(toBack: viewController.view)
viewController.view.translatesAutoresizingMaskIntoConstraints = false
viewController.didMove(toParentViewController: self)
view.addConstraint(alignCenterXConstraint(forItem: viewController.view, toItem: centerViewController.view, position: position))
view.addConstraint(alignCenterYConstraint(forItem: viewController.view, toItem: centerViewController.view, position: position))
view.addConstraints(sizeConstraints(forItem: viewController.view, toItem: centerViewController.view))
}
func alignCenterXConstraint(forItem item: UIView, toItem: UIView, position: Position) -> NSLayoutConstraint {
let offset = position == .left ? -self.view.frame.width : position == .right ? toItem.frame.width : 0
return NSLayoutConstraint(item: item, attribute: .centerX, relatedBy: .equal, toItem: toItem, attribute: .centerX, multiplier: 1, constant: offset)
}
func alignCenterYConstraint(forItem item: UIView, toItem: UIView, position: Position) -> NSLayoutConstraint {
let offset = position == .top ? -self.view.frame.height : position == .bottom ? toItem.frame.height : 0
return NSLayoutConstraint(item: item, attribute: .centerY, relatedBy: .equal, toItem: toItem, attribute: .centerY, multiplier: 1, constant: offset)
}
func sizeConstraints(forItem item: UIView, toItem: UIView) -> [NSLayoutConstraint] {
let widthConstraint = NSLayoutConstraint(item: item, attribute: .width, relatedBy: .equal, toItem: toItem, attribute: .width, multiplier: 1, constant: 0)
let heightConstraint = NSLayoutConstraint(item: item, attribute: .height, relatedBy: .equal, toItem: toItem, attribute: .height, multiplier: 1, constant: 0)
return [widthConstraint, heightConstraint]
}
func hideButtons() {
UIView.animate(withDuration: 0.25) {
self.flipCameraButton.alpha = 0.0
}
}
func showButtons() {
UIView.animate(withDuration: 0.25) {
self.flipCameraButton.alpha = 1.0
}
}
func focusAnimationAt(_ point: CGPoint) {
let focusView = UIImageView(image: #imageLiteral(resourceName: "focus"))
focusView.center = point
focusView.alpha = 0.0
view.addSubview(focusView)
UIView.animate(withDuration: 0.25, delay: 0.0, options: .curveEaseInOut, animations: {
focusView.alpha = 1.0
focusView.transform = CGAffineTransform(scaleX: 1.25, y: 1.25)
}) { (success) in
UIView.animate(withDuration: 0.15, delay: 0.5, options: .curveEaseInOut, animations: {
focusView.alpha = 0.0
focusView.transform = CGAffineTransform(translationX: 0.6, y: 0.6)
}) { (success) in
focusView.removeFromSuperview()
}
}
}
func toggleFlashAnimation() {
if flashEnabled == true {
//flashButton.setImage(#imageLiteral(resourceName: "flash"), for: UIControlState())
} else {
//flashButton.setImage(#imageLiteral(resourceName: "flashOutline"), for: UIControlState())
}
}
}
CameraViewControler -
class CameraViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
UIApplication.shared.statusBarStyle = .lightContent
navigationController?.isNavigationBarHidden = true
}
}