สตอรีบอร์ด, รหัส, เคล็ดลับและ Gotchas ไม่กี่
คำตอบอื่น ๆ นั้นใช้ได้ แต่คำตอบนี้เน้นข้อ จำกัด เล็กน้อยที่สำคัญพอสมควรของข้อ จำกัด การเคลื่อนไหวโดยใช้ตัวอย่างล่าสุด ฉันผ่านการเปลี่ยนแปลงมากมายก่อนที่ฉันจะรู้สิ่งต่อไปนี้:
สร้างข้อ จำกัด ที่คุณต้องการกำหนดเป้าหมายเป็นตัวแปรคลาสเพื่อเก็บการอ้างอิงที่คาดเดายาก ใน Swift ฉันใช้ตัวแปรขี้เกียจ:
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!
}()
หลังจากการทดลองบางอย่างฉันสังเกตเห็นว่าหนึ่งต้องได้รับข้อ จำกัด จากมุมมองข้างต้น (aka กำกับดูแล) ทั้งสองมุมมองที่มีการกำหนดข้อ จำกัด ในตัวอย่างด้านล่าง (ทั้ง MNGStarRating และ UIWebView เป็นไอเท็มสองประเภทที่ฉันสร้างข้อ จำกัด ระหว่างและพวกมันคือ subviews ภายใน self.view)
ตัวกรองเชน
ฉันใช้ประโยชน์จากวิธีการกรองของ Swift เพื่อแยกข้อ จำกัด ที่ต้องการซึ่งจะทำหน้าที่เป็นจุดเปลี่ยนทิศทาง อาจมีความซับซ้อนมากกว่านี้ แต่ตัวกรองทำงานได้ดีที่นี่
ข้อ จำกัด การเคลื่อนไหวโดยใช้ Swift
Nota Bene - ตัวอย่างนี้เป็นสตอรีบอร์ด / การแก้ปัญหารหัสและสมมติว่ามีการกำหนดค่าเริ่มต้นไว้ในกระดานเรื่องราว หนึ่งสามารถเคลื่อนไหวการเปลี่ยนแปลงโดยใช้รหัส
สมมติว่าคุณสร้างคุณสมบัติเพื่อกรองด้วยเกณฑ์ที่ถูกต้องและไปที่จุดผันเฉพาะสำหรับภาพเคลื่อนไหวของคุณ (แน่นอนว่าคุณสามารถกรองอาร์เรย์และวนลูปได้หากคุณต้องการข้อ จำกัด หลายประการ):
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 บางครั้งเมื่อไม่มีอะไรเกิดขึ้นคุณควรซ่อนมุมมองอื่น ๆ หรือใช้มุมมองดีบักเกอร์เพื่อค้นหามุมมองภาพเคลื่อนไหวของคุณ ฉันยังพบกรณีที่ผู้ใช้ระบุ Runtime Attribute หายไปใน xml ของกระดานเรื่องราวและนำไปสู่มุมมองภาพเคลื่อนไหวที่ครอบคลุม (ขณะทำงาน)
ใช้เวลาสักครู่เพื่ออ่านเอกสาร (ใหม่และเก่า) ความช่วยเหลือด่วนและส่วนหัว Apple ทำการเปลี่ยนแปลงมากมายเพื่อจัดการข้อ จำกัด AutoLayout ให้ดียิ่งขึ้น (ดูมุมมองสแต็ก) หรืออย่างน้อยautolayout ตำรา โปรดทราบว่าบางครั้งโซลูชันที่ดีที่สุดอยู่ในเอกสาร / วิดีโอรุ่นเก่า
เล่นกับค่าในภาพเคลื่อนไหวและพิจารณาใช้ตัวแปร animateWithDuration อื่น ๆ
อย่า hardcode ค่าเค้าโครงที่เฉพาะเจาะจงเป็นเกณฑ์ในการพิจารณาการเปลี่ยนแปลงค่าคงที่อื่น ๆ แทนใช้ค่าที่ช่วยให้คุณกำหนดตำแหน่งของมุมมอง CGRectContainsRect
เป็นตัวอย่างหนึ่ง
- หากจำเป็นอย่าลังเลที่จะใช้ระยะขอบเค้าโครงที่เกี่ยวข้องกับมุมมองที่มีส่วนร่วมในคำจำกัดความของข้อ จำกัด
let viewMargins = self.webview.layoutMarginsGuide
: เป็นตัวอย่าง
- ไม่ทำงานคุณไม่ต้องทำมุมมองทั้งหมดที่มีข้อ จำกัด บนกระดานเรื่องราวมีข้อ จำกัด ที่แนบมากับคุณสมบัติ self.viewName.constraints
- เปลี่ยนลำดับความสำคัญของคุณสำหรับข้อ จำกัด น้อยกว่า 1,000 ฉันตั้งค่าของฉันเป็น 250 (ต่ำ) หรือ 750 (สูง) บนกระดานเรื่องราว (หากคุณพยายามเปลี่ยนลำดับความสำคัญ 1,000 รายการเป็นรหัสแอปจะหยุดทำงานเนื่องจากจำเป็นต้องใช้ 1,000 รายการ)
- พิจารณาไม่พยายามใช้ activConfaints ทันทีและปิดการใช้งานข้อ จำกัด (พวกเขามีที่ของพวกเขา แต่เมื่อเรียนรู้หรือถ้าคุณใช้กระดานเรื่องราวโดยใช้สิ่งเหล่านี้อาจหมายถึงว่าคุณทำมากเกินไป ~ พวกเขามีสถานที่ตามที่เห็นด้านล่าง)
- พิจารณาไม่ใช้ addConstraints / removeConstraints เว้นแต่คุณจะเพิ่มข้อ จำกัด ใหม่ในรหัส ฉันพบว่าเกือบทุกครั้งที่ฉันจัดวางมุมมองในกระดานเรื่องราวด้วยข้อ จำกัด ที่ต้องการ (วางหน้าจอการดู) จากนั้นในรหัสฉันเคลื่อนไหวข้อ จำกัด ที่สร้างไว้ก่อนหน้านี้ในกระดานเรื่องราวเพื่อย้ายมุมมองไปรอบ ๆ
- ฉันใช้เวลามากในการสร้างข้อ จำกัด กับคลาสและคลาสย่อยของ NSAnchorLayout ใหม่ งานเหล่านี้ใช้ได้ดี แต่ฉันต้องใช้เวลาสักพักกว่าจะรู้ว่าข้อ จำกัด ทั้งหมดที่ฉันต้องการมีอยู่แล้วในกระดานเรื่องราว หากคุณสร้างข้อ จำกัด ในโค้ดแน่นอนที่สุดแล้วใช้วิธีนี้เพื่อรวมข้อ จำกัด ของคุณ:
ตัวอย่างโซลูชันที่รวดเร็วเพื่อหลีกเลี่ยงเมื่อใช้สตอรีบอร์ด
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
}()
หากคุณลืมหนึ่งในเคล็ดลับเหล่านี้หรือเคล็ดลับง่ายๆเช่นตำแหน่งที่จะเพิ่มเลย์เอาท์หากจำเป็นต้องไม่มีสิ่งใดเกิดขึ้น: ในกรณีนี้คุณอาจมีวิธีแก้ปัญหาแบบครึ่งหน้าเช่นนี้:
NB - ใช้เวลาสักครู่เพื่ออ่านส่วนการเลย์เอาต์อัตโนมัติด้านล่างและคำแนะนำดั้งเดิม มีวิธีใช้เทคนิคเหล่านี้เพื่อเสริม Dynamic Animators ของคุณ
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];
สำหรับผู้ที่เรียนรู้ได้ดีสายตาตรวจสอบต้นนี้วิดีโอจากแอปเปิ้ล
ตั้งใจฟังให้ดี
บ่อยครั้งในเอกสารมีบันทึกย่อขนาดเล็กหรือชิ้นส่วนของรหัสที่นำไปสู่ความคิดที่ใหญ่กว่า ตัวอย่างเช่นการแนบข้อ จำกัด เลย์เอาต์อัตโนมัติกับแอนิเมชั่นแบบไดนามิกเป็นแนวคิดใหญ่
ขอให้โชคดีและบังคับให้อยู่กับคุณ