ฉันสามารถปิดใช้งานการจัดวางอัตโนมัติสำหรับมุมมองย่อยเฉพาะที่รันไทม์ได้หรือไม่


104

ฉันมีมุมมองที่ต้องมีการจัดการเฟรมโดยใช้โปรแกรม - เป็นมุมมองเอกสารประเภทหนึ่งที่ครอบคลุมเนื้อหาซึ่งจะถูกเลื่อนและซูมไปรอบ ๆ ซูเปอร์วิวโดยจัดการกับจุดเริ่มต้นของเฟรม Autolayout ต่อสู้กับสิ่งนี้ที่รันไทม์

การปิดการใช้งานระบบอัตโนมัติโดยสิ้นเชิงดูเหมือนจะค่อนข้างรุนแรงเนื่องจากสามารถใช้เพื่อจัดการเลย์เอาต์สำหรับมุมมองอื่น ๆ ได้อย่างสมเหตุสมผล ดูเหมือนว่าสิ่งที่ฉันต้องการคือ "null constraint" บางอย่าง

คำตอบ:


168

ผมมีปัญหาเหมือนกัน. แต่ฉันได้รับการแก้ไขแล้ว
ได้คุณสามารถปิดใช้งานการจัดวางอัตโนมัติที่รันไทม์สำหรับบางรายการUIViewแทนที่จะปิดใช้งานสำหรับ xib หรือสตอรี่บอร์ดทั้งหมดซึ่งตั้งค่าเป็นค่าเริ่มต้นใน Xcode 4.3 และใหม่กว่า

ตั้งค่าtranslatesAutoresizingMaskIntoConstraintsเป็นYESก่อนที่คุณจะกำหนดกรอบของมุมมองย่อยของคุณ:

self.exampleView.translatesAutoresizingMaskIntoConstraints = YES;
self.exampleView.frame = CGRectMake(20, 20, 50, 50);

2
ดูเหมือนว่าจะมากเกินไปสำหรับบางกรณีที่ซับซ้อนมากขึ้นและมีจำนวนการดูจำนวนมาก สำหรับบางสิ่งที่เรียบง่ายเช่นนี้นี่ก็โอเค
esh

@MuhammadAamirALi ลบมุมมองย่อยแล้วเพิ่มกลับอาจทำให้ประสิทธิภาพลดลงเราสามารถเก็บโซลูชันที่ดีกว่านี้ได้หรือไม่
Nhat Dinh

2
@DinhNhat ฉันชี้แจงคำตอบ ไม่จำเป็นต้องลบและเพิ่มมุมมองย่อยใหม่
Leandros

5
มันแสดงคำเตือน: "ไม่สามารถปฏิบัติตามข้อ จำกัด พร้อมกันได้"
NSPratik

1
คุณบันทึกวัน ... translatesAutoresizingMaskIntoConstraints ของฉัน ... ที่ประดิษฐ์คุณสมบัติเช่นนี้shakinghead
Tintenklecks

50

ฉันมีปัญหาคล้ายกันที่ Autolayout กำลังลบล้างการตั้งค่าเฟรมบางส่วนของฉันในขณะทำงาน (ฉันมีมุมมองแบบไดนามิกที่ในบางกรณีผลักตัวควบคุมมุมมองใหม่ ... การกดแล้วกดย้อนกลับจะเป็นการรีเซ็ตมุมมองเริ่มต้น)

ฉันทำได้โดยการใส่รหัสการจัดการviewDidLayoutSubviewsของฉันใน View Controller ของฉัน สิ่งนี้ดูเหมือนว่าจะถูกเรียกหลังจาก mojo ข้อ จำกัด ใด ๆ ถูกเรียก แต่ก่อน viewDidAppear ดังนั้นผู้ใช้จึงไม่มีใครฉลาดกว่า


1
ไม่ทำงานสำหรับ self.navigationItem.titleView ยังไม่เคารพการเปลี่ยนแปลงกรอบ
Henrik Erlandsson

1
หากคุณกำลังพยายามทำให้กรอบของมุมมองหัวเรื่องฉันจะใส่ไว้ในมุมมองคอนเทนเนอร์และเพิ่มมุมมองคอนเทนเนอร์เป็นมุมมองที่กำหนดเองของ navigationItem
jmstone617

2
สิ่งนี้ได้ผลสำหรับฉันเช่นกัน ฉันเสียเวลาไป 2 ชม.: 22 ม. โขกหัวพิงกำแพงสุภาษิตก่อนที่จะค้นพบวิธีแก้ปัญหานี้
TMc

ขอบคุณผู้ชาย ฉันกำลังดิ้นรนกับปัญหานี้เป็นวันที่สองและตอนนี้ก็ใช้ได้แล้ว!
apostolov

28

บางทีการตั้งค่าtranslatesAutoresizingMaskIntoConstraintsเป็นYES(และไม่เพิ่มข้อ จำกัด เพิ่มเติมที่มีผลต่อมุมมองนั้น) จะช่วยให้คุณตั้งค่าเฟรมได้โดยไม่ต้องต่อสู้กับระบบเลย์เอาต์อัตโนมัติ


17

ใน iOS 8 คุณสามารถตั้งค่า NSLayoutConstraint ให้ใช้งานได้หรือไม่ ดังนั้นถ้าฉันใช้ตัวสร้างอินเทอร์เฟซฉันจะเพิ่มข้อ จำกัด ทั้งหมดของฉันลงใน OutletCollection แล้วเปิดใช้งานหรือปิดใช้งานโดยใช้:

NSLayoutConstraint.deactivateConstraints(self.landscapeConstraintsPad)
NSLayoutConstraint.activateConstraints(self.portraitConstraintsPad)

แอปพลิเคชั่นเฉพาะที่ฉันใช้สำหรับที่นี่มีข้อ จำกัด ที่แตกต่างกันในโหมดแนวตั้งและแนวนอนและฉันเปิด / ปิดการใช้งานตามการหมุนของอุปกรณ์ หมายความว่าฉันสามารถสร้างการเปลี่ยนแปลงเลย์เอาต์ที่ซับซ้อนได้ทั้งหมดในตัวสร้างอินเทอร์เฟซสำหรับทั้งการวางแนวและยังคงใช้การจัดวางอัตโนมัติโดยไม่ต้องใช้โค้ดโครงร่างอัตโนมัติแบบละเอียด

หรือคุณสามารถเปิดใช้งาน / ปิดใช้งานโดยใช้ removeConstraints และ addConstraints


ขออภัยที่หักหลังคำถามเก่า ๆ เช่นนี้ แต่ฉันขอถามได้ไหมว่าคุณจัดการเพิ่มข้อ จำกัด การจัดวางสำหรับเลย์เอาต์ที่แตกต่างกันตั้งแต่แรกได้อย่างไร ฉันไม่พบตัวเลือกในตัวสร้างอินเทอร์เฟซเพื่อเปิด / ปิดการใช้งานข้อ จำกัด หรือคุณเพียงแค่เพิ่มข้อ จำกัด สำหรับทั้งสองเลย์เอาต์และเพิกเฉยต่อตัวสร้างอินเทอร์เฟซที่บ่นเกี่ยวกับข้อ จำกัด ที่ไม่ถูกต้อง (ลบล้าง)?
Malte

คุณสามารถทำได้โดยใช้คลาสขนาด: developer.apple.com/library/ios/recipes/…แต่ฉันทำแบบนี้ไม่ได้เพราะฉันรองรับ iOS 7 ด้วยและคลาสขนาดไม่รองรับ iOS 7 อย่างสมบูรณ์ . ฉันทำได้โดยลดลำดับความสำคัญของข้อ จำกัด ที่ขัดแย้งกัน ไม่เหมาะ แต่เป็นการป้องกันการเตือน ฉันคิดว่านี่เป็นวิธีที่ฉันทำอยู่แล้ว ....
bandejapaisa

9

ฉันไม่รู้ว่าสิ่งนี้จะช่วยคนอื่นได้ไหม แต่ฉันเขียนหมวดหมู่เพื่อให้สะดวกเพราะฉันพบว่าตัวเองทำสิ่งนี้บ่อยมาก

UIView + DisableAutolayoutTempo ชั่วคราว.h

#import <UIKit/UIKit.h>

@interface UIView (DisableAutolayoutTemporarily)

// the view as a parameter is a convenience so we don't have to always
// guard against strong-reference cycles
- (void)resizeWithBlock:(void (^)(UIView *view))block;

@end

UIView + DisableAutolayoutTempo ชั่วคราว m

#import "UIView+DisableAutoResizeTemporarily.h"
@implementation UIView (DisableAutoResizeTemporarily)

- (void)resizeWithBlock:(void (^)(UIView * view))block
{
    UIView *superview = self.superview;
    [self removeFromSuperview];
    [self setTranslatesAutoresizingMaskIntoConstraints:YES];
    __weak UIView *weakSelf = self;
    block(weakSelf);
    [superview addSubview:self];
}

@end

ฉันใช้มันดังนี้:

[cell.argumentLabel resizeWithBlock:^(UIView *view) {
    [view setFrame:frame];
}];

หวังว่าจะช่วยได้


ยอดเยี่ยม! ฉันใช้โค้ดของคุณในเวอร์ชันแก้ไขเพื่อเขียนฟังก์ชัน "hideControl" แบบธรรมดาสำหรับ UIView ใด ๆ โดยทั่วไปจะตั้งค่าความสูงของ UIView เป็น 0 แต่ที่สำคัญคือใช้รหัสของคุณเพื่อให้ AutoLayout จัดการได้อย่างเหมาะสม (ไม่เหมือนกับการใช้ "someView.hidden = TRUE") ดังนั้นการควบคุมที่ปรากฏด้านล่างตัวควบคุมที่ซ่อนอยู่และมีระยะห่างแนวตั้งที่เชื่อมโยงกับมันตอนนี้จะเลื่อนขึ้นบนหน้าจอเพื่อเติมช่องว่างที่ซึ่งมุมมองที่ซ่อนอยู่ก่อนหน้านี้ปรากฏขึ้น
Mike Gledhill

6

คุณสามารถตั้งค่าtranslatesAutoresizingMaskIntoConstraintsประเภทBooleanValue Yes ใน User Defined Runtime Attributes ของ UIView ที่คุณต้องการใน xib / storyboard


2
  • เปิดโครงการใน 4.5
  • เลือกสตอรี่บอร์ด
  • เปิดตัวตรวจสอบไฟล์
  • ภายใต้เอกสารตัวสร้างอินเทอร์เฟซให้ยกเลิกการเลือก 'ใช้การจัดวางอัตโนมัติ'

คุณสามารถแบ่งสตอรีบอร์ดหลาย ๆ อันได้หากต้องการใช้การจัดวางอัตโนมัติสำหรับบางมุมมอง


10
ซึ่งปิดใช้งานการจัดวางอัตโนมัติสำหรับสตอรี่บอร์ด / ปลายปากกาทั้งหมด สิ่งที่ฉันกำลังมองหาคือวิธีหนึ่ง (ในเชิงโปรแกรมที่เป็นโปรแกรม) เพื่อให้มีมุมมองย่อยที่เฉพาะเจาะจงภายในกระดานเรื่องราว / ปลายปากกาไม่ใช้การจัดวางอัตโนมัติในขณะที่ปล่อยให้ส่วนที่เหลือทำอะไรก็ได้ตามที่ระบุไว้
terriblememory

คุณสามารถใช้สตอรี่บอร์ดหลาย ๆ อันและเรียกใช้สตอรี่บอร์ดโดย / ไม่มีการจัดเรียงอัตโนมัติได้ตามต้องการ: // เริ่มต้นตัวควบคุมมุมมองสตอร์บอร์ดและรายละเอียดสำหรับแสดง UIStoryboard * sb = [UIStoryboard storyboardWithName: @ บันเดิล "Storyboard": [NSBundle mainBundle]]; DetailViewController * dvController = [sb instantiateViewControllerWithIdentifier: entry.viewName];
Mike Bobbitt

2

ในมุมมองของฉันฉันมีป้ายกำกับและข้อความ ฉลากมีท่าทางกระทะ ป้ายกำกับจะเคลื่อนที่ไปมาได้ดีในระหว่างการลาก แต่เมื่อฉันใช้แป้นพิมพ์กล่องข้อความป้ายจะรีเซ็ตตำแหน่งเป็นตำแหน่งเดิมที่กำหนดไว้ในรูปแบบอัตโนมัติ ปัญหาได้รับการแก้ไขแล้วเมื่อฉันเพิ่มสิ่งต่อไปนี้อย่างรวดเร็วสำหรับป้ายกำกับ ฉันเพิ่มสิ่งนี้ใน viewWillAppear แต่สามารถเพิ่มได้ทุกที่ที่คุณเข้าถึงฟิลด์เป้าหมาย

self.captionUILabel.translatesAutoresizingMaskIntoConstraints = true

1

สำหรับฉันมันใช้งานได้เพื่อสร้างมุมมองย่อยโดยใช้โปรแกรมในกรณีของฉันเลย์เอาต์อัตโนมัติยุ่งกับมุมมองที่ฉันต้องหมุนรอบจุดศูนย์กลาง แต่เมื่อฉันสร้างมุมมองนี้โดยใช้โปรแกรมแล้วมันก็ใช้งานได้


0

สิ่งนี้เกิดขึ้นกับฉันในโปรเจ็กต์ที่ไม่มีสตอรีบอร์ดหรือไฟล์ xib รหัส 100% ทั้งหมด ฉันมีแบนเนอร์โฆษณาที่ด้านล่างและต้องการให้ขอบเขตการดูหยุดอยู่ที่แบนเนอร์โฆษณา มุมมองจะปรับขนาดเองโดยอัตโนมัติหลังจากโหลด ฉันลองใช้ความละเอียดทุกอย่างในหน้านี้แล้ว แต่ก็ไม่ได้ผล

ฉันลงเอยด้วยการสร้างมุมมองย่อยด้วยความสูงที่สั้นลงและวางไว้ในมุมมองหลักของคอนโทรลเลอร์ จากนั้นเนื้อหาทั้งหมดของฉันก็เข้าไปในมุมมองย่อย นั่นแก้ปัญหาได้ง่ายมากโดยไม่ต้องทำอะไรที่รู้สึกว่าขัดกับเมล็ดข้าว

ฉันคิดว่าถ้าคุณต้องการมุมมองที่ไม่ใช่ขนาดปกติที่เต็มหน้าต่างคุณควรใช้มุมมองย่อยสำหรับสิ่งนั้น


0

ฉันพบสถานการณ์ที่คล้ายกันซึ่งฉันเข้าร่วมโครงการที่เริ่มต้นด้วยการจัดวางอัตโนมัติ แต่ฉันจำเป็นต้องทำการปรับเปลี่ยนแบบไดนามิกสำหรับหลายมุมมอง นี่คือสิ่งที่ได้ผลสำหรับฉัน:

  1. ห้ามมีมุมมองหรือส่วนประกอบในตัวสร้างอินเทอร์เฟซ

  2. เพิ่มมุมมองของคุณโดยใช้โปรแกรมอย่างเดียวโดยเริ่มจากการจัดสรร / เริ่มต้นและตั้งค่าเฟรมให้เหมาะสม

  3. เสร็จแล้ว


0

แทนที่จะปิดการใช้งานการเลือกอัตโนมัติฉันจะคำนวณข้อ จำกัด ใหม่กับเฟรมที่คุณกำลังเปลี่ยน ดูเหมือนว่าฉันจะเป็นวิธีที่เหมาะสม หากคุณกำลังปรับส่วนประกอบที่ต้องอาศัยข้อ จำกัด ให้ปรับเปลี่ยนตามนั้น

ตัวอย่างเช่นหากคุณมีข้อ จำกัด ในแนวตั้งที่ 0 ระหว่างสองมุมมอง (myView และอื่น ๆ View) และคุณมีท่าทางการแพนหรือสิ่งที่ปรับความสูงของ myView คุณสามารถคำนวณข้อ จำกัด ใหม่ด้วยค่าที่ปรับแล้ว

self.verticalConstraint.constant = newMyViewYOriginValue - (self.otherView.frame.origin.y + self.otherView.frame.size.height);
[self.myView needsUpdateConstraints];

0

สำหรับบรรดาของคุณที่มีการใช้รูปแบบอัตโนมัติกรุณาตรวจสอบแก้ปัญหาของฉันที่นี่ คุณควรทำ@IBOutletตามข้อ จำกัด ที่คุณต้องการปรับแล้วเปลี่ยนค่าคงที่


-16

ถ้าเป็นไฟล์ xib:

  1. เลือกไฟล์. xib
  2. เลือก "เจ้าของไฟล์"
  3. แสดงยูทิลิตี้
  4. คลิกที่: "File Inspector"
  5. ในส่วน "Interface Builder Document" ปิดใช้งาน: "Use Autolayout"

1
ไม่นั่นเป็นการปิดใช้งานการกำหนดค่าอัตโนมัติสำหรับ xib ทั้งหมด สิ่งที่ฉันกำลังมองหาคือวิธีที่จะนำมุมมองย่อยเพียงรายการเดียวออกจากระบบการจัดวางอัตโนมัติ
hormemory
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.