चूँकि यह Google पर शीर्ष परिणाम है, मैंने सोचा कि मैं जो सबसे अधिक समझदार तरीका है उसे साझा करूँगा; जो iOS 7+ ट्रांस्फ़ॉर्मिंग API का उपयोग करने के लिए है। मैंने इसे स्विफ्ट 3 के साथ iOS 10 के लिए लागू किया।
UINavigationControllerयदि आप एक उप-वर्ग बनाते हैं UINavigationControllerऔर UIViewControllerAnimatedTransitioningप्रोटोकॉल के अनुरूप होते हैं तो उस वर्ग का एक उदाहरण लौटाते हैं, जिसे दो दृश्य नियंत्रकों के बीच कैसे एनिमेट किया जाता है, इसे संयोजित करना बहुत सरल है ।
उदाहरण के लिए यहाँ मेरा UINavigationControllerउपवर्ग है:
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)
}
}
आप देख सकते हैं कि मैंने UINavigationControllerDelegateखुद को सेट किया है, और मेरे उपवर्ग पर विस्तार में मैं उस पद्धति को लागू करता हूं UINavigationControllerDelegateजिससे आप एक कस्टम एनीमेशन नियंत्रक (यानी, NavigationControllerAnimation) को वापस कर सकते हैं । यह कस्टम एनीमेशन कंट्रोलर आपके लिए स्टॉक एनीमेशन को बदल देगा।
आप शायद सोच रहे हैं कि मैं ऑपरेशन में NavigationControllerAnimationइसके इनिशलाइज़र के माध्यम से क्यों गुजरता हूं । मैं ऐसा इसलिए करता हूं कि प्रोटोकॉल के NavigationControllerAnimationकार्यान्वयन में UIViewControllerAnimatedTransitioningमुझे पता है कि ऑपरेशन क्या है (यानी, 'पुश' या 'पॉप')। इससे यह जानने में मदद मिलती है कि मुझे किस तरह का एनीमेशन करना चाहिए। अधिकांश समय, आप ऑपरेशन के आधार पर एक अलग एनीमेशन करना चाहते हैं।
बाकी बहुत मानक है। UIViewControllerAnimatedTransitioningप्रोटोकॉल और चेतन में दो आवश्यक कार्यों को लागू करें, लेकिन आप जैसे हैं:
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
}
}
}
यह याद रखना महत्वपूर्ण है कि प्रत्येक अलग प्रकार के ऑपरेशन के लिए (जैसे, 'पुश' या 'पॉप), से और देखने के लिए नियंत्रक अलग-अलग होंगे। जब आप एक पुश ऑपरेशन में होते हैं, तो नियंत्रक को देखने के लिए धक्का दिया जाएगा। जब आप किसी पॉप ऑपरेशन में होते हैं, तो कंट्रोलर देखने वाला वह होगा जिसे संक्रमण किया जा रहा है, और व्यू कंट्रोलर वह होगा जो पॉपप हो रहा है।
इसके अलावा, संक्रमण के संदर्भ में toदृश्य नियंत्रक को उप-भाग के रूप में जोड़ा जाना चाहिए containerView।
जब आपका एनीमेशन पूरा हो जाता है, तो आपको कॉल करना होगा transitionContext.completeTransition(true)। आप एक इंटरैक्टिव संक्रमण कर रहे हैं, तो आप गतिशील रूप से एक वापस करने के लिए करना होगा Boolकरने के लिए completeTransition(didComplete: Bool)संक्रमण एनीमेशन के अंत में पूरा हो गया है, तो के आधार पर,।
अंत में ( वैकल्पिक पठन ), आप यह देखना चाहते होंगे कि मैंने जिस संक्रमण पर काम कर रहा था, उसे कैसे किया। यह कोड थोड़ा अधिक हैकी है और मैंने इसे बहुत जल्दी लिखा है इसलिए मैं इसे महान एनीमेशन कोड नहीं कहूँगा लेकिन यह अभी भी दिखाता है कि एनीमेशन भाग को कैसे करना है।
मेरा एक बहुत ही सरल संक्रमण था; मैं उसी एनीमेशन की नकल करना चाहता था जो UINavigationController आम तौर पर करता है, लेकिन इसके बजाय 'अगला पृष्ठ ओवर द टॉप' एनीमेशन करता है, मैं पुराने दृश्य नियंत्रक के 1: 1 एनीमेशन को उसी समय लागू करना चाहता था जैसे कि नया दृश्य नियंत्रक प्रकट होता है। इससे दो दृश्य नियंत्रकों के रूप में ऐसा प्रतीत होता है कि जैसे वे एक दूसरे के लिए पिन किए जाते हैं।
पुश ऑपरेशन के लिए, जिसे toViewControllerस्क्रीन के x- अक्ष पर मूल दृश्य को सेट करने की आवश्यकता होती है , इसे सब-वे के रूप में जोड़कर containerView, इसे origin.xशून्य पर सेट करके स्क्रीन पर एनिमेट कर रहा है। उसी समय, मैं स्क्रीन को बंद fromViewControllerकरके दृश्य को दूर करता हूं origin.x:
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)
})
पॉप ऑपरेशन मूल रूप से उलटा है। जोड़े toViewControllerकी एक subview के रूप containerViewहै, और दूर चेतन fromViewControllerसही करने के लिए के रूप में आप में चेतन toViewControllerबाएं से:
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)
})
यहाँ पूरी स्विफ्ट फ़ाइल के साथ एक जिस्ट है:
https://gist.github.com/alanzeino/603293f9da5cd0b7f6b60dc20bc766be