UIViewPropertyAnimator 无法通过视图之间的平移手势正确停止
UIViewPropertyAnimator not stopping properly with pan gesture between views
我有一个视图控制器,它设置了 3 个子视图控制器,将三个视图并排放置,并将中间视图居中.. 就像 snapchat。视图控制器之间的滑动是通过使用调整最左侧子视图控制器的左锚点约束的手势来控制的。
现在...当我平移然后放手时,它会转到正确的约束条件。
问题:当我平移、松开、再次平移时,约束突然弹回并且动画看起来不正确。任何见解将不胜感激....
这个 link 展示了我所说的约束和动画捕捉和时髦的意思!! (第一个平底锅是正确的,但是当我试图打断第二个平底锅时,你会看到我的问题)
https://giphy.com/gifs/mEDld5sbR81gJBHcl1
import UIKit
class ViewController: UIViewController {
private let viewControllerOne = UIViewController()
private let viewControllerTwo = UIViewController()
private let viewControllerThree = UIViewController()
private var viewControllerOneLeftAnchorConstraint: NSLayoutConstraint?
override func loadView() {
view = UIView()
view.backgroundColor = .white
//removed code for Whosebug readability, here i setup view controllers and pangestures
guard let viewControllerOneLeftAnchorConstraint = viewControllerOneLeftAnchorConstraint else { return }
NSLayoutConstraint.activate([
viewControllerOne.view.topAnchor.constraint(equalTo: view.topAnchor),
viewControllerTwo.view.topAnchor.constraint(equalTo: view.topAnchor),
viewControllerThree.view.topAnchor.constraint(equalTo: view.topAnchor),
viewControllerOne.view.bottomAnchor.constraint(equalTo: view.bottomAnchor),
viewControllerTwo.view.bottomAnchor.constraint(equalTo: view.bottomAnchor),
viewControllerThree.view.bottomAnchor.constraint(equalTo: view.bottomAnchor),
viewControllerOne.view.widthAnchor.constraint(equalTo: view.widthAnchor),
viewControllerTwo.view.widthAnchor.constraint(equalTo: view.widthAnchor),
viewControllerThree.view.widthAnchor.constraint(equalTo: view.widthAnchor),
viewControllerOneLeftAnchorConstraint,
viewControllerTwo.view.leftAnchor.constraint(equalTo: viewControllerOne.view.rightAnchor),
viewControllerThree.view.leftAnchor.constraint(equalTo: viewControllerTwo.view.rightAnchor),
])
}
private var animator: UIViewPropertyAnimator?
private var previous: CGPoint?
private var current: CGPoint?
@objc private func handlePan(gesture: UIPanGestureRecognizer) {
guard let viewControllerOneLeftAnchorConstraint = viewControllerOneLeftAnchorConstraint else { return }
if gesture.state == .began {
previous = gesture.location(in: view)
animator?.stopAnimation(true)
} else if gesture.state == .changed {
let current = gesture.location(in: view)
guard let previous = previous else { return }
let xPositionDifference = current.x - previous.x
if viewControllerOneLeftAnchorConstraint.constant + xPositionDifference < 0 && viewControllerOneLeftAnchorConstraint.constant + xPositionDifference > -(UIScreen.main.bounds.width * 2) {
self.viewControllerOneLeftAnchorConstraint?.constant += xPositionDifference
self.previous = current
}
} else if gesture.state == .ended {
viewControllerOneLeftAnchorConstraint.constant = calculateLeftAnchorConstant(viewControllerOneLeftAnchorConstraint: viewControllerOneLeftAnchorConstraint)
animator = UIViewPropertyAnimator(duration: 2.0, curve: .easeOut) {
self.view.layoutIfNeeded()
}
animator?.startAnimation()
}
}
func calculateLeftAnchorConstant(viewControllerOneLeftAnchorConstraint: NSLayoutConstraint) -> CGFloat {
if viewControllerOneLeftAnchorConstraint.constant <= 0
&& viewControllerOneLeftAnchorConstraint.constant > -(UIScreen.main.bounds.width/2.0) {
return 0.0
} else if viewControllerOneLeftAnchorConstraint.constant > -(UIScreen.main.bounds.width/2.0 * 3)
&& viewControllerOneLeftAnchorConstraint.constant < -(UIScreen.main.bounds.width/2.0) {
return -(UIScreen.main.bounds.width)
} else {
return -(UIScreen.main.bounds.width * 2)
}
}
}
我建议您放弃整个代码。您的文字和动画 gif 描述的是 UIPageViewController,那么为什么不使用 UIPageViewController?
我有一个视图控制器,它设置了 3 个子视图控制器,将三个视图并排放置,并将中间视图居中.. 就像 snapchat。视图控制器之间的滑动是通过使用调整最左侧子视图控制器的左锚点约束的手势来控制的。
现在...当我平移然后放手时,它会转到正确的约束条件。
问题:当我平移、松开、再次平移时,约束突然弹回并且动画看起来不正确。任何见解将不胜感激....
这个 link 展示了我所说的约束和动画捕捉和时髦的意思!! (第一个平底锅是正确的,但是当我试图打断第二个平底锅时,你会看到我的问题)
https://giphy.com/gifs/mEDld5sbR81gJBHcl1
import UIKit
class ViewController: UIViewController {
private let viewControllerOne = UIViewController()
private let viewControllerTwo = UIViewController()
private let viewControllerThree = UIViewController()
private var viewControllerOneLeftAnchorConstraint: NSLayoutConstraint?
override func loadView() {
view = UIView()
view.backgroundColor = .white
//removed code for Whosebug readability, here i setup view controllers and pangestures
guard let viewControllerOneLeftAnchorConstraint = viewControllerOneLeftAnchorConstraint else { return }
NSLayoutConstraint.activate([
viewControllerOne.view.topAnchor.constraint(equalTo: view.topAnchor),
viewControllerTwo.view.topAnchor.constraint(equalTo: view.topAnchor),
viewControllerThree.view.topAnchor.constraint(equalTo: view.topAnchor),
viewControllerOne.view.bottomAnchor.constraint(equalTo: view.bottomAnchor),
viewControllerTwo.view.bottomAnchor.constraint(equalTo: view.bottomAnchor),
viewControllerThree.view.bottomAnchor.constraint(equalTo: view.bottomAnchor),
viewControllerOne.view.widthAnchor.constraint(equalTo: view.widthAnchor),
viewControllerTwo.view.widthAnchor.constraint(equalTo: view.widthAnchor),
viewControllerThree.view.widthAnchor.constraint(equalTo: view.widthAnchor),
viewControllerOneLeftAnchorConstraint,
viewControllerTwo.view.leftAnchor.constraint(equalTo: viewControllerOne.view.rightAnchor),
viewControllerThree.view.leftAnchor.constraint(equalTo: viewControllerTwo.view.rightAnchor),
])
}
private var animator: UIViewPropertyAnimator?
private var previous: CGPoint?
private var current: CGPoint?
@objc private func handlePan(gesture: UIPanGestureRecognizer) {
guard let viewControllerOneLeftAnchorConstraint = viewControllerOneLeftAnchorConstraint else { return }
if gesture.state == .began {
previous = gesture.location(in: view)
animator?.stopAnimation(true)
} else if gesture.state == .changed {
let current = gesture.location(in: view)
guard let previous = previous else { return }
let xPositionDifference = current.x - previous.x
if viewControllerOneLeftAnchorConstraint.constant + xPositionDifference < 0 && viewControllerOneLeftAnchorConstraint.constant + xPositionDifference > -(UIScreen.main.bounds.width * 2) {
self.viewControllerOneLeftAnchorConstraint?.constant += xPositionDifference
self.previous = current
}
} else if gesture.state == .ended {
viewControllerOneLeftAnchorConstraint.constant = calculateLeftAnchorConstant(viewControllerOneLeftAnchorConstraint: viewControllerOneLeftAnchorConstraint)
animator = UIViewPropertyAnimator(duration: 2.0, curve: .easeOut) {
self.view.layoutIfNeeded()
}
animator?.startAnimation()
}
}
func calculateLeftAnchorConstant(viewControllerOneLeftAnchorConstraint: NSLayoutConstraint) -> CGFloat {
if viewControllerOneLeftAnchorConstraint.constant <= 0
&& viewControllerOneLeftAnchorConstraint.constant > -(UIScreen.main.bounds.width/2.0) {
return 0.0
} else if viewControllerOneLeftAnchorConstraint.constant > -(UIScreen.main.bounds.width/2.0 * 3)
&& viewControllerOneLeftAnchorConstraint.constant < -(UIScreen.main.bounds.width/2.0) {
return -(UIScreen.main.bounds.width)
} else {
return -(UIScreen.main.bounds.width * 2)
}
}
}
我建议您放弃整个代码。您的文字和动画 gif 描述的是 UIPageViewController,那么为什么不使用 UIPageViewController?