Vì đây là kết quả hàng đầu trên Google, tôi nghĩ tôi muốn chia sẻ những gì tôi nghĩ là cách lành mạnh nhất; đó là sử dụng API chuyển tiếp iOS 7+. Tôi đã triển khai điều này cho iOS 10 với Swift 3.
Thật đơn giản để kết hợp điều này với cách hoạt UINavigationController
hình giữa hai bộ điều khiển khung nhìn nếu bạn tạo một lớp con UINavigationController
và trả về một thể hiện của một lớp phù hợp với UIViewControllerAnimatedTransitioning
giao thức.
Ví dụ ở đây là UINavigationController
lớp con của tôi :
class NavigationController: UINavigationController {
init() {
super.init(nibName: nil, bundle: nil)
delegate = self
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
extension NavigationController: UINavigationControllerDelegate {
public func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationControllerOperation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return NavigationControllerAnimation(operation: operation)
}
}
Bạn có thể thấy rằng tôi đặt UINavigationControllerDelegate
chính nó và trong một phần mở rộng trên lớp con của tôi, tôi triển khai phương thức trong UINavigationControllerDelegate
đó cho phép bạn trả về bộ điều khiển hoạt hình tùy chỉnh (nghĩa là NavigationControllerAnimation
). Bộ điều khiển hoạt hình tùy chỉnh này sẽ thay thế hình ảnh động cho bạn.
Có lẽ bạn đang tự hỏi tại sao tôi chuyển hoạt động sang NavigationControllerAnimation
thể hiện thông qua trình khởi tạo của nó. Tôi làm điều này để trong NavigationControllerAnimation
quá trình thực hiện UIViewControllerAnimatedTransitioning
giao thức, tôi biết thao tác là gì (nghĩa là 'đẩy' hoặc 'pop'). Điều này giúp biết loại hoạt hình nào tôi nên làm. Hầu hết thời gian, bạn muốn thực hiện một hình ảnh động khác nhau tùy thuộc vào hoạt động.
Phần còn lại là khá chuẩn. Thực hiện hai chức năng cần thiết trong UIViewControllerAnimatedTransitioning
giao thức và hoạt hình theo cách bạn muốn:
class NavigationControllerAnimation: NSObject, UIViewControllerAnimatedTransitioning {
let operation: UINavigationControllerOperation
init(operation: UINavigationControllerOperation) {
self.operation = operation
super.init()
}
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 0.3
}
public func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
guard let fromViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from),
let toViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to) else { return }
let containerView = transitionContext.containerView
if operation == .push {
// do your animation for push
} else if operation == .pop {
// do your animation for pop
}
}
}
Điều quan trọng cần nhớ là, đối với mỗi loại hoạt động khác nhau (nghĩa là 'đẩy' hoặc 'pop), bộ điều khiển xem và từ sẽ khác nhau. Khi bạn đang ở trong một hoạt động đẩy, bộ điều khiển để xem sẽ là bộ điều khiển được đẩy. Khi bạn đang ở trong một hoạt động pop, bộ điều khiển để xem sẽ là bộ điều khiển đang được chuyển sang và bộ điều khiển từ chế độ xem sẽ là bộ điều khiển được bật.
Ngoài ra, to
bộ điều khiển xem phải được thêm dưới dạng một khung nhìn phụ containerView
trong bối cảnh chuyển tiếp.
Khi hoạt hình của bạn hoàn thành, bạn phải gọi transitionContext.completeTransition(true)
. Nếu bạn đang làm một sự chuyển tiếp tương tác, bạn sẽ phải tự động trả về một Bool
tới completeTransition(didComplete: Bool)
, tùy thuộc vào nếu quá trình chuyển đổi hoàn tất vào cuối của phim hoạt hình.
Cuối cùng ( đọc tùy chọn ), bạn có thể muốn xem tôi đã thực hiện quá trình chuyển đổi như thế nào. Mã này hơi khó sử dụng hơn một chút và tôi đã viết nó khá nhanh vì vậy tôi sẽ không nói đó là mã hoạt hình tuyệt vời nhưng nó vẫn chỉ ra cách thực hiện phần hoạt hình.
Của tôi là một quá trình chuyển đổi thực sự đơn giản; Tôi muốn bắt chước hoạt hình tương tự như UINavestionControll thường làm, nhưng thay vì hoạt hình 'trang tiếp theo trên đầu trang', tôi muốn triển khai hoạt hình 1: 1 của trình điều khiển chế độ xem cũ cùng lúc với chế độ xem mới bộ điều khiển xuất hiện. Điều này có tác dụng làm cho hai bộ điều khiển khung nhìn có vẻ như chúng được ghim vào nhau.
Đối với thao tác đẩy, trước tiên, yêu cầu thiết lập toViewController
nguồn gốc chế độ xem trên màn hình tắt trục x, thêm nó vào chế độ xem phụ containerView
, tạo hiệu ứng trên màn hình bằng cách đặt giá trị đó origin.x
thành 0. Đồng thời, tôi làm nổi bật fromViewController
tầm nhìn của mình bằng cách origin.x
tắt màn hình:
toViewController.view.frame = containerView.bounds.offsetBy(dx: containerView.frame.size.width, dy: 0.0)
containerView.addSubview(toViewController.view)
UIView.animate(withDuration: transitionDuration(using: transitionContext),
delay: 0,
options: [ UIViewAnimationOptions.curveEaseOut ],
animations: {
toViewController.view.frame = containerView.bounds
fromViewController.view.frame = containerView.bounds.offsetBy(dx: -containerView.frame.size.width, dy: 0)
},
completion: { (finished) in
transitionContext.completeTransition(true)
})
Các hoạt động pop về cơ bản là nghịch đảo. Thêm phần toViewController
dưới dạng một khung nhìn phụ containerView
và tạo hiệu fromViewController
ứng từ bên phải khi bạn tạo hình động toViewController
từ bên trái:
containerView.addSubview(toViewController.view)
UIView.animate(withDuration: transitionDuration(using: transitionContext),
delay: 0,
options: [ UIViewAnimationOptions.curveEaseOut ],
animations: {
fromViewController.view.frame = containerView.bounds.offsetBy(dx: containerView.frame.width, dy: 0)
toViewController.view.frame = containerView.bounds
},
completion: { (finished) in
transitionContext.completeTransition(true)
})
Đây là một ý chính với toàn bộ tập tin nhanh chóng:
https://gist.github.com/alanzeino/603293f9da5cd0b7f6b60dc20bc766be