स्टोरीबोर्ड, कोड, टिप्स और कुछ गोटेच
अन्य उत्तर ठीक हैं, लेकिन यह एक हालिया उदाहरण का उपयोग करते हुए बाधाओं को कम करने के कुछ महत्वपूर्ण महत्वपूर्ण पर प्रकाश डाला गया है। निम्नलिखित का एहसास होने से पहले मैं बहुत भिन्नताओं से गुज़रा:
एक मजबूत संदर्भ रखने के लिए आप उन अवरोधों को बनाएं जिन्हें आप कक्षा चर में लक्षित करना चाहते हैं। स्विफ्ट में मैंने आलसी चर का उपयोग किया:
lazy var centerYInflection:NSLayoutConstraint = {
let temp = self.view.constraints.filter({ $0.firstItem is MNGStarRating }).filter ( { $0.secondItem is UIWebView }).filter({ $0.firstAttribute == .CenterY }).first
return temp!
}()
कुछ प्रयोग के बाद मैंने नोट किया कि एक को ABOVE (उर्फ पर्यवेक्षणीय) को दो दृष्टिकोणों से कसना प्राप्त होता है जहां कसना परिभाषित किया गया है। नीचे दिए गए उदाहरण में (दोनों MNGStarRating और UIWebView दो प्रकार के आइटम हैं जिनके बीच मैं एक बाधा पैदा कर रहा हूं, और वे स्वयं के भीतर साक्षात्कार हैं)।
छानने का काम
मैं स्विफ्ट के फिल्टर विधि का लाभ उठाता हूं ताकि वांछित बिंदु को अलग किया जा सके जो विभक्ति बिंदु के रूप में काम करेगा। एक भी अधिक जटिल हो सकता है, लेकिन फ़िल्टर यहाँ एक अच्छा काम करता है।
एनिमेटेड स्विफ्ट का उपयोग करते हुए बाधाओं
नोटा बेने - यह उदाहरण स्टोरीबोर्ड / कोड समाधान है और मानता है कि किसी ने स्टोरीबोर्ड में डिफ़ॉल्ट बाधाएं बनाई हैं। फिर कोड का उपयोग करके परिवर्तन को चेतन किया जा सकता है।
मान लें कि आप सटीक मानदंड के साथ फ़िल्टर करने के लिए एक संपत्ति बनाते हैं और अपने एनीमेशन के लिए एक विशिष्ट विभक्ति बिंदु प्राप्त करते हैं (बेशक आप कई बाधाओं के लिए एक सरणी और लूप के लिए फ़िल्टर कर सकते हैं)
lazy var centerYInflection:NSLayoutConstraint = {
let temp = self.view.constraints.filter({ $0.firstItem is MNGStarRating }).filter ( { $0.secondItem is UIWebView }).filter({ $0.firstAttribute == .CenterY }).first
return temp!
}()
....
कुछ समय बाद...
@IBAction func toggleRatingView (sender:AnyObject){
let aPointAboveScene = -(max(UIScreen.mainScreen().bounds.width,UIScreen.mainScreen().bounds.height) * 2.0)
self.view.layoutIfNeeded()
//Use any animation you want, I like the bounce in springVelocity...
UIView.animateWithDuration(1.0, delay: 0.0, usingSpringWithDamping: 0.3, initialSpringVelocity: 0.75, options: [.CurveEaseOut], animations: { () -> Void in
//I use the frames to determine if the view is on-screen
if CGRectContainsRect(self.view.frame, self.ratingView.frame) {
//in frame ~ animate away
//I play a sound to give the animation some life
self.centerYInflection.constant = aPointAboveScene
self.centerYInflection.priority = UILayoutPriority(950)
} else {
//I play a different sound just to keep the user engaged
//out of frame ~ animate into scene
self.centerYInflection.constant = 0
self.centerYInflection.priority = UILayoutPriority(950)
self.view.setNeedsLayout()
self.view.layoutIfNeeded()
}) { (success) -> Void in
//do something else
}
}
}
कई गलत मोड़
ये नोट वास्तव में युक्तियों का एक सेट है जो मैंने खुद के लिए लिखा था। मैंने व्यक्तिगत रूप से और दर्द से सभी काम नहीं किए। उम्मीद है कि यह गाइड दूसरों को बख्श सकता है।
ZPositioning के लिए बाहर देखो। कभी-कभी जब स्पष्ट रूप से कुछ भी नहीं हो रहा होता है, तो आपको कुछ अन्य दृश्यों को छिपाना चाहिए या अपने एनिमेटेड दृश्य का पता लगाने के लिए व्यू डीबगर का उपयोग करना चाहिए। मुझे ऐसे मामले भी मिले हैं, जहां एक उपयोगकर्ता परिभाषित रनटाइम अट्रैक्शन स्टोरीबोर्ड के xml में खो गया था और एनिमेटेड दृश्य को कवर किया गया था (काम करते समय)।
प्रलेखन (नए और पुराने), त्वरित सहायता और हेडर पढ़ने के लिए हमेशा एक मिनट का समय लें। AutoLayout बाधाओं को बेहतर तरीके से प्रबंधित करने के लिए Apple बहुत सारे बदलाव करता रहता है (स्टैक विचार देखें)। या कम से कम AutoLayout रसोई की किताब । ध्यान रखें कि कभी-कभी सबसे अच्छा समाधान पुराने प्रलेखन / वीडियो में होते हैं।
एनीमेशन में मूल्यों के साथ चारों ओर खेलें और अन्य चेतनता अवधि वेरिएंट का उपयोग करने पर विचार करें।
अन्य स्थिरांक में परिवर्तन निर्धारित करने के मापदंड के रूप में विशिष्ट लेआउट मानों को हार्डकोड न करें, इसके बजाय उन मानों का उपयोग करें जो आपको दृश्य के स्थान को निर्धारित करने की अनुमति देते हैं। CGRectContainsRect
एक उदाहरण है
- यदि आवश्यक हो, तो बाधा परिभाषा में भाग लेने वाले दृश्य से जुड़े लेआउट मार्जिन का उपयोग करने में संकोच न करें
let viewMargins = self.webview.layoutMarginsGuide
: उदाहरण के लिए
- वह काम न करें जो आपको नहीं करना है, स्टोरीबोर्ड पर बाधाओं के साथ सभी विचारों को संपत्ति से जुड़ी बाधाएं हैं।
- 1000 से कम के लिए किसी भी बाधाओं के लिए अपनी प्राथमिकताएं बदलें। मैंने स्टोरीबोर्ड पर 250 (कम) या 750 (उच्च) के लिए मेरा सेट किया; (यदि आप किसी कोड में 1000 प्राथमिकता को बदलने की कोशिश करते हैं तो ऐप क्रैश हो जाएगा क्योंकि 1000 की आवश्यकता है)
- तुरंत सक्रियण का उपयोग करने की कोशिश नहीं करने पर विचार करें औरConstraints को निष्क्रिय करें (उनके पास अपनी जगह है लेकिन जब आप सीख रहे हैं या यदि आप इनका उपयोग करके एक स्टोरीबोर्ड का उपयोग कर रहे हैं, तो इसका मतलब है कि आपका बहुत अधिक ~ वे एक जगह है हालांकि नीचे जैसा देखा गया है)
- AddConstraints / removeConstraints का उपयोग न करने पर विचार करें जब तक कि आप वास्तव में कोड में एक नई बाधा नहीं जोड़ रहे हों। मैंने पाया कि ज्यादातर बार मैं स्टोरीबोर्ड में विचारों को वांछित बाधाओं (दृश्य को ऑफस्क्रीन रखते हुए) के साथ लेआउट करता हूं, फिर कोड में, मैं पहले दृश्य को स्थानांतरित करने के लिए स्टोरीबोर्ड में बनाई गई बाधाओं को चेतन करता हूं।
- मैंने नए NSAnchorLayout वर्ग और उपवर्गों के साथ बाधाओं का निर्माण करने में बहुत समय बर्बाद किया। ये ठीक काम करते हैं लेकिन मुझे यह महसूस करने में थोड़ा समय लगा कि स्टोरीबोर्ड में पहले से मौजूद सभी बाधाओं की मुझे जरूरत थी। यदि आप कोड में बाधाओं का निर्माण करते हैं तो निश्चित रूप से इस पद्धति का उपयोग अपनी बाधाओं को एकत्र करने के लिए करें:
स्टोरीबोर्ड का उपयोग करते समय AVOID को समाधान का त्वरित नमूना
private var _nc:[NSLayoutConstraint] = []
lazy var newConstraints:[NSLayoutConstraint] = {
if !(self._nc.isEmpty) {
return self._nc
}
let viewMargins = self.webview.layoutMarginsGuide
let minimumScreenWidth = min(UIScreen.mainScreen().bounds.width,UIScreen.mainScreen().bounds.height)
let centerY = self.ratingView.centerYAnchor.constraintEqualToAnchor(self.webview.centerYAnchor)
centerY.constant = -1000.0
centerY.priority = (950)
let centerX = self.ratingView.centerXAnchor.constraintEqualToAnchor(self.webview.centerXAnchor)
centerX.priority = (950)
if let buttonConstraints = self.originalRatingViewConstraints?.filter({
($0.firstItem is UIButton || $0.secondItem is UIButton )
}) {
self._nc.appendContentsOf(buttonConstraints)
}
self._nc.append( centerY)
self._nc.append( centerX)
self._nc.append (self.ratingView.leadingAnchor.constraintEqualToAnchor(viewMargins.leadingAnchor, constant: 10.0))
self._nc.append (self.ratingView.trailingAnchor.constraintEqualToAnchor(viewMargins.trailingAnchor, constant: 10.0))
self._nc.append (self.ratingView.widthAnchor.constraintEqualToConstant((minimumScreenWidth - 20.0)))
self._nc.append (self.ratingView.heightAnchor.constraintEqualToConstant(200.0))
return self._nc
}()
यदि आप इन युक्तियों में से किसी एक या अधिक सरल को भूल जाते हैं, जैसे कि लेआउट को कहां जोड़ा जाए। यदि ऐसा किया जाता है, तो सबसे अधिक संभावना है कि कुछ भी नहीं होगा: इस मामले में आपके पास इस तरह का आधा बेक किया हुआ समाधान हो सकता है:
एनबी - नीचे दिए गए ऑटोलॉयट सेक्शन और मूल गाइड को पढ़ने के लिए कुछ समय निकालें। अपने डायनेमिक एनिमेटरों को पूरक करने के लिए इन तकनीकों का उपयोग करने का एक तरीका है।
UIView.animateWithDuration(1.0, delay: 0.0, usingSpringWithDamping: 0.3, initialSpringVelocity: 1.0, options: [.CurveEaseOut], animations: { () -> Void in
//
if self.starTopInflectionPoint.constant < 0 {
//-3000
//offscreen
self.starTopInflectionPoint.constant = self.navigationController?.navigationBar.bounds.height ?? 0
self.changeConstraintPriority([self.starTopInflectionPoint], value: UILayoutPriority(950), forView: self.ratingView)
} else {
self.starTopInflectionPoint.constant = -3000
self.changeConstraintPriority([self.starTopInflectionPoint], value: UILayoutPriority(950), forView: self.ratingView)
}
}) { (success) -> Void in
//do something else
}
}
AutoLayout गाइड से स्निपेट (ध्यान दें कि दूसरा स्निपेट OS X का उपयोग करने के लिए है)। BTW - यह अब तक के मौजूदा गाइड में नहीं है जहां तक मैं देख सकता हूं। पसंदीदा तकनीकों का विकास जारी है।
ऑटो लेआउट द्वारा किए गए परिवर्तन एनिमेटेड
यदि आपको ऑटो लेआउट द्वारा किए गए परिवर्तनों को पूरा करने पर पूर्ण नियंत्रण की आवश्यकता है, तो आपको अपने अवरोधों को प्रोग्रामेटिक रूप से बदलना होगा। मूल अवधारणा iOS और OS X दोनों के लिए समान है, लेकिन कुछ मामूली अंतर हैं।
एक iOS ऐप में, आपका कोड कुछ इस तरह दिखाई देगा:
[containerView layoutIfNeeded]; // Ensures that all pending layout operations have been completed
[UIView animateWithDuration:1.0 animations:^{
// Make all constraint changes here
[containerView layoutIfNeeded]; // Forces the layout of the subtree animation block and then captures all of the frame changes
}];
OS X में, परत-समर्थित एनिमेशन का उपयोग करते समय निम्नलिखित कोड का उपयोग करें:
[containterView layoutSubtreeIfNeeded];
[NSAnimationContext runAnimationGroup:^(NSAnimationContext *context) {
[context setAllowsImplicitAnimation: YES];
// Make all constraint changes here
[containerView layoutSubtreeIfNeeded];
}];
जब आप परत-समर्थित एनिमेशन का उपयोग नहीं कर रहे हैं, तो आपको बाधा के एनीमेटर का उपयोग करके निरंतर को चेतन करना होगा:
[[constraint animator] setConstant:42];
जो लोग बेहतर सीखते हैं उनके लिए Apple के इस शुरुआती वीडियो को देखें ।
विशेस ध्यान दें
अक्सर प्रलेखन में छोटे नोट या कोड के टुकड़े होते हैं जो बड़े विचारों को जन्म देते हैं। उदाहरण के लिए डायनेमिक एनिमेटरों के लिए ऑटो लेआउट बाधाओं को जोड़ना एक बड़ा विचार है।
गुड लक और मे द फोर्स आपके साथ हो।