iOS: หนึ่งจะเคลื่อนไหวไปยังข้อ จำกัด การกำหนดค่าอัตโนมัติใหม่ (ความสูง) ได้อย่างไร


123

ผมไม่เคยทำงานร่วมกับautolayoutจำกัด ก่อน ฉันมีแอปใหม่ขนาดเล็กที่ฉันกำลังทำงานอยู่และสังเกตเห็นว่ามุมมองของ NIB เป็นค่าเริ่มต้นของการกำหนดค่าอัตโนมัติ ดังนั้นฉันคิดว่าฉันจะใช้โอกาสนี้ในการทำงานกับมันและพยายามคิดว่า Apple จะไปที่ไหนกับสิ่งนี้

ความท้าทายแรก:

ฉันต้องการปรับขนาด MKMapView และฉันต้องการทำให้มันเคลื่อนไหวไปยังตำแหน่งใหม่ ถ้าฉันทำแบบนี้เหมือนเคย:

[UIView animateWithDuration:1.2f
     animations:^{
         CGRect theFrame = worldView.frame;
         CGRect newFrame = CGRectMake(theFrame.origin.x, theFrame.origin.y, theFrame.size.width, theFrame.size.height - 170);
         worldView.frame = newFrame;
}];

... จากนั้น MKMapView จะ 'snap' กลับสู่ความสูงเดิมเมื่อใดก็ตามที่มีการอัปเดตมุมมองพี่น้อง (ในกรณีของฉันมีการอัปเดตชื่อของ UISegmentedControl [myUISegmentedControl setTitle:newTitle forSegmentAtIndex:0])

ดังนั้นสิ่งที่ฉันคิดว่าฉันต้องการจะทำคือการเปลี่ยนข้อ จำกัด ของ MKMapView จากการถูกเท่ากับสูงมุมมองของผู้ปกครองที่จะเป็นญาติไปด้านบนของ UISegmentedControl ว่ามันถูกครอบคลุม:V:[MKMapView]-(16)-[UISegmentedControl]

สิ่งที่ฉันต้องการคือให้ความสูง MKMapView สั้นลงเพื่อให้การควบคุมบางอย่างใต้มุมมองแผนที่ถูกเปิดเผย ในการทำเช่นนั้นฉันคิดว่าฉันต้องเปลี่ยนข้อ จำกัด จากมุมมองขนาดเต็มคงที่เป็นมุมมองที่ด้านล่างถูก จำกัด ไว้ที่ด้านบนของ UISegmentedControl ... และฉันต้องการให้มันเคลื่อนไหวเมื่อมุมมองลดลงเป็นขนาดใหม่

จะไปเกี่ยวกับเรื่องนี้ได้อย่างไร?

แก้ไข - ภาพเคลื่อนไหวนี้ไม่เคลื่อนไหวแม้ว่าด้านล่างของมุมมองจะขยับขึ้น 170 ทันที:

    [UIView animateWithDuration:1.2f
         animations:^{
             self.nibMapViewConstraint.constant = -170;

    }];

และต่อnibMapViewConstraintสายใน IB ไปยังข้อ จำกัด ด้านพื้นที่แนวตั้งด้านล่าง


1
ฉันรู้ว่าคุณสามารถเปลี่ยนค่าคงที่ของข้อ จำกัด ในบล็อก [UIView animateWithDuration .. ] เพื่อทำให้การเปลี่ยนแปลงความสูงเคลื่อนไหวได้ คุณต้องสร้าง IBOutlet สำหรับข้อ จำกัด นั้นและต่อเข้าใน xib ของคุณหรือไม่ก็ให้อ้างอิงหากคุณสร้างในโค้ด (หรือวนรอบข้อ จำกัด ทั้งหมดเพื่อค้นหา) ไม่แน่ใจว่าจะเคลื่อนไหว relatedBy ได้อย่างไร แต่ฉันอ่านแล้วว่าคุณควรเปลี่ยนค่าคงที่เท่านั้นไม่ใช่ค่าอื่น ๆ ของข้อ จำกัด (สำหรับค่าอื่นให้สร้างข้อ จำกัด ใหม่)
yuf

อืมมม คิดว่าฉันทำได้ แต่ฉันไม่เคลื่อนไหว มันเปลี่ยนแปลงสำเร็จและอยู่ในบล็อคแอนิเมชั่น แต่ไม่เคลื่อนไหว!?!
Meltemi

พบคำตอบของฉันที่นี่: < stackoverflow.com/questions/12926566/… >
Meltemi

1
อย่าลืม [view layoutIfNeeded] นั่นก็เป็นปัญหาของฉันเช่นกันฮ่าฮ่า นั่นเป็นคำถามเดียวกับที่ช่วยแก้ปัญหาของฉัน
yuf

คำตอบ:


179

หลังจากอัปเดตข้อ จำกัด ของคุณ:

[UIView animateWithDuration:0.5 animations:^{[self.view layoutIfNeeded];}];

แทนที่self.viewด้วยการอ้างอิงถึงมุมมองที่มี


4
ที่ใช้งานได้กับมุมมองนั้น ๆ อย่างไรก็ตามมุมมองที่มีข้อ จำกัด ในการดูนั้นจะย้ายไปทันที ฉันจะทำอย่างไร? ty
dietbacon

7
คุณต้องเรียกเค้าโครงหากจำเป็นในมุมมองเหล่านั้นด้วย อย่างไรก็ตามมันทำงานไม่ถูกต้องจริง ๆ เนื่องจากจะทำให้การรีเฟรชมุมมองเคลื่อนไหวเช่นกัน คุณจะทำให้การปรับข้อ จำกัด เฉพาะในมุมมองอื่น ๆ เคลื่อนไหวได้อย่างไร?
ngb

3
ระวัง:หากใช้UIViewAnimationOptionBeginFromCurrentStateข้อ จำกัด ของเลย์เอาต์จะถูกตั้งค่าก่อนแอนิเมชั่น!
Robert

12
แทนที่จะเรียกดูlayoutIfNeededแต่ละมุมมองเหล่านั้นเพียงแค่โทร[[self.view superview] layoutIfNeeded];
Flying_Banana

2
@ngb คุณต้องเปลี่ยนค่าคงที่ข้อ จำกัดภายในบล็อกภาพเคลื่อนไหว ด้วยวิธีนี้ข้อ จำกัด จะเปลี่ยนไปตามภาพเคลื่อนไหวและคุณสามารถใช้UIViewAnimationOptionBeginFromCurrentStateต่อได้
Eran Goldin

86

สิ่งนี้ใช้ได้กับฉัน (ทั้ง iOS7 และ iOS8 +) คลิกที่ข้อ จำกัด การจัดวางอัตโนมัติที่คุณต้องการปรับเปลี่ยน (ในตัวสร้างอินเทอร์เฟซเช่นข้อ จำกัด ด้านบน) ต่อไปให้เป็น IBOutlet

@property (strong, nonatomic) IBOutlet NSLayoutConstraint *topConstraint;

เคลื่อนไหวขึ้นไป;

    self.topConstraint.constant = -100;    
    [self.viewToAnimate setNeedsUpdateConstraints]; 
    [UIView animateWithDuration:1.5 animations:^{
        [self.viewToAnimate layoutIfNeeded]; 
    }];

ย้ายกลับไปที่เดิม

    self.topConstraint.constant = 0;    
    [self.viewToAnimate setNeedsUpdateConstraints];  
    [UIView animateWithDuration:1.5 animations:^{
        [self.viewToAnimate layoutIfNeeded];
    }];

2
ว้าว!! มันใช้งานได้จริง! คำตอบนี้เปิดหูเปิดตาสำหรับฉัน ขอบคุณมาก! - Erik
Erik van der Neut

2
@ErikvanderNeut สำหรับฉันเช่นกันดีใจที่มีประโยชน์ ต่อจากนี้ไปฉันจะเคลื่อนไหวข้อ จำกัด มากกว่าตำแหน่งเฟรม
DevC

อย่าพลาดที่จะเพิ่ม: [containerView layoutIfNeeded]; เพื่อให้แน่ใจว่าการดำเนินการเลย์เอาต์ที่รอดำเนินการทั้งหมดเสร็จสมบูรณ์ก่อนบล็อก animateWithDuration
ingconti

11

มีบทช่วยสอนที่ดีมากจากแอปเปิลเองที่อธิบายวิธีการใช้แอนิเมชั่นกับการจัดวางอัตโนมัติ ไปที่ลิงก์นี้จากนั้นค้นหาวิดีโอชื่อ "การจัดวางอัตโนมัติตามตัวอย่าง" ซึ่งจะให้ข้อมูลที่น่าสนใจเกี่ยวกับการจัดวางอัตโนมัติและส่วนสุดท้ายจะเกี่ยวกับวิธีใช้ภาพเคลื่อนไหว


3

ฉันได้ทำการสาธิตขนาดเล็กนี้แล้ว มันแสดงให้เห็นว่าข้อ จำกัด ของการจัดวางอัตโนมัติสามารถเปลี่ยนแปลงและเคลื่อนไหวได้อย่างไรในตัวอย่างง่ายๆ เพียงแค่ใช้เวลาดูที่DemoViewController.m


1

คนส่วนใหญ่ใช้การจัดวางอัตโนมัติเพื่อจัดวางรายการตามมุมมองและแก้ไขข้อ จำกัด ของการจัดวางเพื่อสร้างภาพเคลื่อนไหว

วิธีง่ายๆในการทำสิ่งนี้โดยไม่ต้องใช้รหัสมากนักคือการสร้าง UIView ที่คุณต้องการทำให้เคลื่อนไหวใน Storyboard จากนั้นสร้าง UIView ที่ซ่อนอยู่ซึ่งคุณต้องการให้ UIView สิ้นสุดลง คุณสามารถใช้การแสดงตัวอย่างใน xcode เพื่อให้แน่ใจว่า UIView ทั้งสองอยู่ในที่ที่คุณต้องการ หลังจากนั้นซ่อน UIView ตอนจบและสลับข้อ จำกัด ของเค้าโครง

มี podfile สำหรับการแลกเปลี่ยนข้อ จำกัด ของโครงร่างที่เรียกว่า SBP หากคุณไม่ต้องการเขียนด้วยตัวเอง

นี่คือการกวดวิชา


0

ไม่จำเป็นต้องใช้IBOutlet referenceข้อ จำกัด เพิ่มเติมแทนสิ่งนี้คุณสามารถใช้ข้อ จำกัดโดยตรงaccessหรือupdateใช้แล้วไม่ว่าจะใช้โดยProgrammaticallyหรือจากInterface Builderมุมมองใด ๆ โดยใช้KVConstraintExtensionsMasterไลบรารี ห้องสมุดนี้นอกจากนี้ยังมีการจัดการพฤติกรรมของCumulativeNSLayoutConstraint

หากต้องการเพิ่มข้อ จำกัด ความสูงบน containerView

 CGFloat height = 200;
 [self.containerView applyHeightConstrain:height];

หากต้องการอัปเดตข้อจำกัดความสูงของ containerView ด้วยภาพเคลื่อนไหว

[self.containerView accessAppliedConstraintByAttribute:NSLayoutAttributeHeight completion:^(NSLayoutConstraint *expectedConstraint){
        if (expectedConstraint) {
            expectedConstraint.constant = 100;

            /* for the animation */ 
            [self.containerView  updateModifyConstraintsWithAnimation:NULL];
      }
    }];
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.