วิธีการใช้เลย์เอาต์อัตโนมัติเพื่อย้ายมุมมองอื่น ๆ เมื่อมุมมองถูกซ่อนอยู่?


333

ฉันได้ออกแบบ Cell ที่กำหนดเองของฉันใน IB แล้วทำการซับคลาสและเชื่อมต่อร้านค้าของฉันกับคลาสที่กำหนดเองของฉัน ฉันมีสามพรีวิวในเนื้อหาของเซลล์ซึ่ง ได้แก่ : UIView (cdView) และสองป้ายกำกับ (titleLabel และ emailLabel) บางครั้งฉันต้องการให้ UIView และป้ายกำกับสองรายการแสดงในเซลล์ของฉันและบางครั้งก็มีป้ายกำกับเพียงสองรายการทั้งนี้ขึ้นอยู่กับข้อมูลที่มีให้สำหรับแต่ละแถว สิ่งที่ฉันพยายามทำคือการตั้งข้อ จำกัด แบบนั้นถ้าฉันตั้งค่าคุณสมบัติ UIView ให้ซ่อนหรือฉันจะลบออกจาก superview ป้ายกำกับทั้งสองจะเลื่อนไปทางซ้าย ฉันพยายามตั้งค่าข้อ จำกัด ที่นำ UIView เป็น Superview (เนื้อหาของเซลล์) สำหรับ 10px และ UILabels นำข้อ จำกัด 10 px ไปยังมุมมองถัดไป (UIView) ต่อมาในรหัสของฉัน

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(IndexPath *)indexPath {
...
Record *record = [self.records objectAtIndex:indexPath.row];

if ([record.imageURL is equalToString:@""]) {
     cell.cdView.hidden = YES;
}

ฉันซ่อน cell.cdView ของฉันและฉันต้องการให้ป้ายกำกับเลื่อนไปทางซ้าย แต่พวกเขายังคงอยู่ในตำแหน่งเดิมใน Cell ฉันพยายามลบ cell.cdView จาก superview แต่มันก็ไม่ได้ผลเหมือนกัน ฉันได้แนบภาพเพื่ออธิบายสิ่งที่ฉันเป็น

เซลล์

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

.....

เปลี่ยนค่าข้อ จำกัด รันไทม์ - ตรวจสอบคำตอบ
Kampai

สำหรับกรณีเฉพาะนี้คุณสามารถใช้ UIStackView เมื่อคุณซ่อนซีดีฉลากจะใช้พื้นที่ของพวกเขา
Marco Pappalardo

คำตอบ:


373

เป็นไปได้ แต่คุณจะต้องทำงานพิเศษเล็กน้อย มีสิ่งต่าง ๆ เกี่ยวกับความคิดสองอย่างที่ควรหลีกทางก่อน:

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

ในกรณีของคุณอาจหมายถึง:

  • หากคุณตั้งค่ามุมมองด้านซ้ายให้ซ่อนป้ายกำกับจะคงอยู่เนื่องจากมุมมองด้านซ้ายนั้นยังคงใช้พื้นที่อยู่ (แม้ว่าจะมองไม่เห็นก็ตาม)
  • หากคุณลบมุมมองซ้ายของคุณป้ายกำกับของคุณอาจถูก จำกัด อย่างคลุมเครือเนื่องจากคุณไม่มีข้อ จำกัด ด้านขอบซ้ายของป้ายกำกับอีกต่อไป

สิ่งที่คุณต้องทำคือจำกัดอย่างรอบคอบฉลากของคุณปล่อยให้ข้อ จำกัด ที่มีอยู่ของคุณ (พื้นที่ 10 พอยต์ไปยังมุมมองอื่น) เพียงอย่างเดียว แต่เพิ่มข้อ จำกัด อื่น: ทำให้ขอบด้านซ้ายของป้ายกำกับของคุณอยู่ห่างจากขอบด้านซ้ายของ superview 10pts ด้วยลำดับความสำคัญที่ไม่จำเป็น

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

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


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

ในความคิดของฉันนี่ไม่ใช่วิธีที่จะไป คุณควรใช้ความกว้าง / ความสูง จำกัด สำหรับมุมมองที่คุณต้องการซ่อน
ullstrm

26
ฉันไม่เห็นด้วยอย่างเคารพ หากคุณ (ตัวอย่าง) ตั้งค่าความกว้างของมุมมองเป็น 0 คุณจะพบปัญหาสองข้อ ครั้งแรกที่คุณตอนนี้มีระยะห่างระหว่างคู่ SuperView และมุมมองที่มองเห็นได้: มีประสิทธิภาพ|-(space)-[hidden(0)]-(space)-[visible] |-(2*space)-[visible]ประการที่สองมุมมองนั้นอาจเริ่มโยนการละเมิดข้อ จำกัด ขึ้นอยู่กับทรีย่อยและมุมมองของตัวเอง - คุณไม่สามารถรับประกันได้ว่าคุณสามารถ จำกัด มุมมองโดยพลการที่ความกว้าง 0 และทำให้มันทำงานต่อไป
ทิม

1
หากคุณกำลังใช้มุมมองที่มีขนาดเนื้อหาที่แท้จริงคำตอบของทิมดูเหมือนจะเป็นวิธีที่ไม่เหมือนใคร
balkoth

ขอบคุณทิม ฉันตั้งค่าข้อ จำกัด เป็น 0 โดยมีลำดับความสำคัญสูงกว่าเพื่อหลีกเลี่ยงความไม่เข้ากันของข้อ จำกัด แต่ตอนนี้ฉันรู้ว่ามีปัญหากับการเว้นวรรคสองครั้ง ฉันไม่ได้มีปัญหานั้นเพราะฉันไม่เคยแสดงสองมุมมองเข้าด้วยกัน (กรณีของฉัน:) |-[otherViews]-[eitherThis][orThis]-|แต่ฉันจะเจอปัญหานั้นในที่สุด
Ferran Maylinch

207

การเพิ่มหรือลบข้อ จำกัด ระหว่างการใช้งานจริงนั้นเป็นการดำเนินการแบบหนาที่อาจส่งผลต่อประสิทธิภาพ อย่างไรก็ตามมีทางเลือกที่ง่ายกว่า

สำหรับมุมมองที่คุณต้องการซ่อนตั้งค่าจำกัดความกว้าง จำกัด มุมมองอื่นด้วยช่องว่างแนวนอนนำไปสู่มุมมองนั้น

หากต้องการซ่อนอัปเดต.constantข้อจำกัดความกว้างเป็น 0.f มุมมองอื่นจะเลื่อนไปทางซ้ายโดยอัตโนมัติเพื่อรับตำแหน่ง

ดูคำตอบอื่น ๆ ของฉันที่นี่สำหรับรายละเอียดเพิ่มเติม:

วิธีการเปลี่ยนข้อ จำกัด ของฉลากระหว่างรันไทม์?


29
ปัญหาเดียวของการแก้ปัญหานี้คือระยะขอบด้านซ้ายจะเป็นสองเท่าของสิ่งที่คุณต้องการดังนั้นฉันจะอัปเดตหนึ่งในข้อ จำกัด เหล่านั้นด้วย แต่ถึงอย่างนั้นฉันก็คิดว่ามันใช้งานได้น้อยกว่า
José Manuel Sánchez

2
@ skinsfan00atg หากคุณใช้มุมมองที่มีขนาดเนื้อหาที่แท้จริงคุณไม่สามารถใช้โซลูชันนี้ได้
บอลข่าน

@balkoth ทำไมไม่? คุณสามารถลดลำดับความสำคัญของการกอดเนื้อหาได้
Max MacLeod

2
@MaxMacLeod หากคุณลดระดับความสำคัญในการกอดเนื้อหาคุณไม่ได้ใช้ขนาดเนื้อหาที่แท้จริงคุณกำลังใช้ขนาดที่ระบุโดยข้อ จำกัด
balkoth

2
@ MaxMacLeod ตกลงฉันเข้าใจสิ่งที่คุณหมายถึง คุณต้องตั้งค่าลำดับความสำคัญการบีบอัดความต้านทานเป็น 0 (ไม่ใช่การกอดเนื้อหา) ในโค้ดเมื่อคุณต้องการซ่อนมุมมองและเมื่อคุณต้องการแสดงอีกครั้งเรียกคืนค่านั้น นอกเหนือจากนั้นคุณต้องเพิ่มข้อ จำกัด ในตัวสร้างส่วนต่อประสานเพื่อตั้งค่าขนาดของมุมมองเป็น 0 ไม่จำเป็นต้องแตะข้อ จำกัด นี้ในรหัส
balkoth

87

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

ร้าน PS Constraint ต้องแข็งแรงไม่อ่อน

ตัวอย่าง:

@IBOutlet weak var optionalView: UIView!
@IBOutlet var viewIsVisibleConstraint: NSLayoutConstraint!
@IBOutlet var viewIsHiddenConstraint: NSLayoutConstraint!

func showView() {
    optionalView.isHidden = false
    viewIsVisibleConstraint.isActive = true
    viewIsHiddenConstraint.isActive = false
}

func hideView() {
    optionalView.isHidden = true
    viewIsVisibleConstraint.isActive = false
    viewIsHiddenConstraint.isActive = true
}

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

UIStackView (iOS 9+)
UIStackViewหนึ่งในตัวเลือกที่มากขึ้นคือการห่อในมุมมองของคุณ เมื่อมุมมองถูกซ่อนไว้UIStackViewจะอัปเดตเค้าโครงโดยอัตโนมัติ


ทำงานได้บางส่วน แต่ถ้าฉันใช้ภายในเซลล์ที่สามารถนำกลับมาใช้ใหม่ได้ตั้งแต่เปิดใช้งานจนถึงปิดใช้งานทำงานได้ แต่ไม่ใช่เพื่อปิดใช้งานเพื่อเปิดใช้งาน ความคิดใด ๆ หรือคุณอาจให้ตัวอย่างบางที
Aoke Li

10
มันเกิดขึ้นเนื่องจากข้อ จำกัด ที่ปิดใช้งานไม่ได้ถูกโหลดหรือยกเลิกการจัดสรรคืน ทางออกที่ จำกัด ของคุณควรแข็งแกร่งไม่อ่อนแอ
Silmaril

เราจะหาคุณสมบัติ "ใช้งาน" ได้ที่ไหน?
ลักษมีเรดดี้


ดูเหมือนว่ากิจกรรมข้อ จำกัด ที่ตั้งเกิน + จะเป็นคำตอบที่สมเหตุสมผลที่สุด
Ting Yi Shih

68

UIStackViewจัดเก็บมุมมองใหม่โดยอัตโนมัติเมื่อhiddenมีการเปลี่ยนแปลงคุณสมบัติในพรีวิวย่อยใด ๆ (iOS 9+)

UIView.animateWithDuration(1.0) { () -> Void in
   self.mySubview.hidden = !self.mySubview.hidden
}

ข้ามไปที่11:48ในวิดีโอ WWDC นี้เพื่อดูตัวอย่าง:

ความลึกลับของเค้าโครงอัตโนมัติตอนที่ 1


ฉันซ่อนมุมมองสแต็กซ้อนและมุมมองสแต็กทั้งหมดที่มีหายไป
Ian Warburton

5
นี่ควรเป็นคำตอบที่ยอมรับได้ การแนะนำแอปเปิ้ลต่อไปนี้ของ wwdc 2015 ในการออกแบบตัวสร้างส่วนต่อประสาน
thibaut noah

@thibautnoah แล้ว iOS 8 รองรับแล้วล่ะ?
สัมภาระ

5
@bagage ยกเว้นว่าคุณเป็น facebook หรือ google คุณสามารถทำมันได้ ด้วยความครอบคลุม beyong iOS 9 คุณจะรองรับอุปกรณ์ได้มากกว่า 90% มากกว่าเพียงพอ การสนับสนุนด้านล่างจะทำลายกระบวนการพัฒนาของคุณและป้องกันไม่ให้คุณใช้คุณสมบัติล่าสุด imo
thibaut noah

16

โครงการของฉันใช้@IBDesignableคลาสย่อยที่กำหนดเองของUILabel(เพื่อให้แน่ใจในความสม่ำเสมอของสีแบบอักษรสิ่งที่ใส่เข้าไป ฯลฯ ) และฉันได้ดำเนินการดังนี้:

override func intrinsicContentSize() -> CGSize {
    if hidden {
        return CGSizeZero
    } else {
        return super.intrinsicContentSize()
    }
}

สิ่งนี้ทำให้คลาสย่อยของเลเบลมีส่วนร่วมในเลย์เอาต์อัตโนมัติ แต่ไม่ต้องเว้นที่ว่างเมื่อซ่อน


13

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

นี่คือตัวอย่างง่ายๆ:

ภาพหน้าจอของ IB

ในกรณีนี้ฉันแมปความสูงของป้ายชื่อผู้แต่งกับความเหมาะสมIBOutlet:

@property (retain, nonatomic) IBOutlet NSLayoutConstraint* authorLabelHeight;

และเมื่อฉันตั้งค่าความสูงของข้อ จำกัด0.0fเราจะรักษา "ระยะห่าง" เนื่องจากความสูงของปุ่มPlayอนุญาตให้ทำได้


สำหรับผู้ที่ยังใหม่กับNSLayoutConstraintผมเชื่อว่าคุณต้องการที่จะปรับปรุงconstantสถานที่ให้บริการauthorLabelHeightของคุณ
Kyle

8

เชื่อมต่อข้อ จำกัด ระหว่าง uiview และป้ายกำกับเป็น IBOutlet และตั้งค่าลำดับความสำคัญของสมาชิกให้มีค่าน้อยลงเมื่อตั้งค่า hidden = YES


3
คุณไม่สามารถปรับระดับความสำคัญของ NSLayoutConstraint เมื่อสร้างเสร็จแล้ว คุณต้องลบและอ่านข้อ จำกัด ใหม่ที่มีลำดับความสำคัญต่างกัน
ทิม

7
ฉันได้รับวิธีการนี้ในการทำงาน ฉันมีกรณีที่ใช้ป้ายกำกับและปุ่มที่ฉันต้องซ่อนปุ่มและมีการขยายฉลาก ฉันมีข้อ จำกัด สองข้อข้อแรกที่มีลำดับความสำคัญ 751 และอีกข้อคือ 750 จากนั้นเมื่อฉันซ่อนปุ่มฉันพลิกลำดับความสำคัญและความยาวของฉลากจะเพิ่มขึ้น ควรสังเกตว่าถ้าคุณพยายามให้ลำดับความสำคัญสูงกว่า 1,000 คุณจะได้รับข้อผิดพลาด "การเปลี่ยนลำดับความสำคัญจากที่ต้องการไม่ใช่ข้อ จำกัด ที่ติดตั้ง (หรือกลับกัน) ไม่ได้รับการสนับสนุน" ดังนั้นอย่าและคุณดูเหมือนจะสบายดี Xcode 5.1 / viewDidLoad
John Bushnell

8

สิ่งที่ฉันทำคือการสร้าง 2 xibs หนึ่งมุมมองด้านซ้ายและอีกมุมมองหนึ่ง ฉันลงทะเบียนทั้งสองในคอนโทรลเลอร์แล้วตัดสินใจว่าจะใช้ระหว่าง cellForRowAtIndexPath หรือไม่

พวกเขาใช้คลาส UITableViewCell เดียวกัน ข้อเสียคือมีการทำซ้ำเนื้อหาระหว่าง xibs แต่เซลล์เหล่านี้ค่อนข้างพื้นฐาน ข้อเสียคือฉันไม่มีรหัสมากมายในการจัดการการลบมุมมองการปรับปรุงข้อ จำกัด ฯลฯ ด้วยตนเอง

โดยทั่วไปนี่น่าจะเป็นทางออกที่ดีกว่าเนื่องจากมีเลย์เอาต์ที่แตกต่างกันในทางเทคนิคดังนั้นจึงควรมี xibs ที่ต่างกัน

[self.table registerNib:[UINib nibWithNibName:@"TrackCell" bundle:nil] forCellReuseIdentifier:@"TrackCell"];
[self.table registerNib:[UINib nibWithNibName:@"TrackCellNoImage" bundle:nil] forCellReuseIdentifier:@"TrackCellNoImage"];

TrackCell *cell = [tableView dequeueReusableCellWithIdentifier:(appDelegate.showImages ? @"TrackCell" : @"TrackCellNoImage") forIndexPath:indexPath];

7

ในกรณีนี้ฉันแมปความสูงของป้ายชื่อผู้แต่งกับ IBOutlet ที่เหมาะสม:

@property (retain, nonatomic) IBOutlet NSLayoutConstraint* authorLabelHeight;

และเมื่อฉันตั้งค่าความสูงของข้อ จำกัด เป็น 0.0f เราจะรักษา "ช่องว่างภายใน" เนื่องจากความสูงของปุ่ม Play อนุญาตให้ทำได้

cell.authorLabelHeight.constant = 0;

ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่


6

ใช้ UIStackView แนวนอนและแนวตั้งสองอันเมื่อมุมมองย่อยในกองซ้อนถูกซ่อนไว้มุมมองกองซ้อนอื่น ๆ จะถูกย้ายให้ใช้การกระจาย -> เติมตามลำดับสำหรับกองซ้อนแนวตั้งที่มี UILabels สองชุดและต้องการกำหนดความกว้างและความสูงสำหรับ UIView แรกป้อนคำอธิบายรูปภาพที่นี่


2

ลองนี้ฉันใช้งานด้านล่างรหัส

ฉันมีมุมมองหนึ่งบนViewControllerในที่เพิ่มอีกสามมุมมองเมื่อมุมมองใดถูกซ่อนอีกสองมุมมองจะย้ายทำตามขั้นตอนด้านล่าง ,

1. ไฟล์ ViewController.h

#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@property (strong, nonatomic) IBOutlet UIView *viewOne;
@property (strong, nonatomic) IBOutlet UIView *viewTwo;
@property (strong, nonatomic) IBOutlet UIView *viewThree;
@property (strong, nonatomic) IBOutlet NSLayoutConstraint *viewOneWidth;
@property (strong, nonatomic) IBOutlet NSLayoutConstraint *viewTwoWidth;
@property (strong, nonatomic) IBOutlet NSLayoutConstraint *viewThreeWidth;
@property (strong, nonatomic) IBOutlet NSLayoutConstraint *viewBottomWidth;
@end

2.ViewController.m

 #import "ViewController.h"
 @interface ViewController ()
{
  CGFloat viewOneWidthConstant;
  CGFloat viewTwoWidthConstant;
  CGFloat viewThreeWidthConstant;
  CGFloat viewBottomWidthConstant;
}
@end

@implementation ViewController
@synthesize viewOne, viewTwo, viewThree;

- (void)viewDidLoad {
  [super viewDidLoad];
 // Do any additional setup after loading the view, typically from a 
  nib.

  /*
   0  0   0
   0  0   1
   0  1   0
   0  1   1
   1  0   0
   1  0   1
   1  1   0
   1  1   1
   */

  //    [viewOne setHidden:NO];
  //    [viewTwo setHidden:NO];
  //    [viewThree setHidden:NO];

  //    [viewOne setHidden:NO];
  //    [viewTwo setHidden:NO];
  //    [viewThree setHidden:YES];

  //    [viewOne setHidden:NO];
  //    [viewTwo setHidden:YES];
  //    [viewThree setHidden:NO];

  //    [viewOne setHidden:NO];
  //    [viewTwo setHidden:YES];
  //    [viewThree setHidden:YES];


  //    [viewOne setHidden:YES];
  //    [viewTwo setHidden:NO];
  //    [viewThree setHidden:NO];

  //    [viewOne setHidden:YES];
  //    [viewTwo setHidden:NO];
  //    [viewThree setHidden:YES];

 //    [viewOne setHidden:YES];
 //    [viewTwo setHidden:YES];
 //    [viewThree setHidden:NO];

//    [viewOne setHidden:YES];
//    [viewTwo setHidden:YES];
//    [viewThree setHidden:YES];

 [self hideShowBottomBar];
  }

- (void)hideShowBottomBar
{
  BOOL isOne = !viewOne.isHidden;
  BOOL isTwo = !viewTwo.isHidden;
  BOOL isThree = !viewThree.isHidden;

  viewOneWidthConstant = _viewOneWidth.constant;
  viewTwoWidthConstant = _viewTwoWidth.constant;
  viewThreeWidthConstant = _viewThreeWidth.constant;
  viewBottomWidthConstant = _viewBottomWidth.constant;

   if (isOne && isTwo && isThree) {
    // 0    0   0
    _viewOneWidth.constant = viewBottomWidthConstant / 3;
    _viewTwoWidth.constant = viewBottomWidthConstant / 3;
    _viewThreeWidth.constant = viewBottomWidthConstant / 3;
    }
    else if (isOne && isTwo && !isThree) {
     // 0    0   1
    _viewOneWidth.constant = viewBottomWidthConstant / 2;
    _viewTwoWidth.constant = viewBottomWidthConstant / 2;
    _viewThreeWidth.constant = 0;
    }
   else if (isOne && !isTwo && isThree) {
    // 0    1   0
    _viewOneWidth.constant = viewBottomWidthConstant / 2;
    _viewTwoWidth.constant = 0;
    _viewThreeWidth.constant = viewBottomWidthConstant / 2;
    }
    else if (isOne && !isTwo && !isThree) {
    // 0    1   1
    _viewOneWidth.constant = viewBottomWidthConstant;
    _viewTwoWidth.constant = 0;
    _viewThreeWidth.constant = 0;
   }
   else if (!isOne && isTwo && isThree) {
    // 1    0   0
    _viewOneWidth.constant = 0;
    _viewTwoWidth.constant = viewBottomWidthConstant / 2;
    _viewThreeWidth.constant = viewBottomWidthConstant / 2;
   }
   else if (!isOne && isTwo && !isThree) {
    // 1    0   1
    _viewOneWidth.constant = 0;
    _viewTwoWidth.constant = viewBottomWidthConstant;
    _viewThreeWidth.constant = 0;
   }
   else if (!isOne && !isTwo && isThree) {
    // 1    1   0
    _viewOneWidth.constant = 0;
    _viewTwoWidth.constant = 0;
    _viewThreeWidth.constant = viewBottomWidthConstant;
   }
   else if (isOne && isTwo && isThree) {
    // 1    1   1
    _viewOneWidth.constant = 0;
    _viewTwoWidth.constant = 0;
    _viewThreeWidth.constant = 0;
   }
  }

 - (void)didReceiveMemoryWarning {
  [super didReceiveMemoryWarning];
 // Dispose of any resources that can be recreated.
 }
 @end

ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่

หวังว่าดังนั้นตรรกะนี้จะช่วยให้ใครบางคน


1

ในกรณีของฉันฉันจะตั้งค่าคงที่ของข้อ จำกัด สูงไป0.0fและยังตั้งhiddenคุณสมบัติการYESคุณสมบัติการ

เพื่อแสดงให้เห็นมุมมอง (กับ subviews) การอีกครั้งที่ผมทำตรงข้าม: ผมตั้งค่าคงที่ความสูงที่ไม่ใช่ศูนย์ที่มีมูลค่าและการตั้งค่าคุณสมบัติการhiddenNO


1

ฉันจะใช้ stackview ในแนวนอน มันสามารถลบเฟรมเมื่อซ่อนย่อยได้

ในภาพด้านล่างมุมมองสีแดงเป็นที่บรรจุจริงสำหรับเนื้อหาของคุณและมีพื้นที่ต่อท้าย 10pt กับส้ม superview (ShowHideView) จากนั้นเพียงเชื่อมต่อ ShowHideView กับ IBOutlet และแสดง / ซ่อน / ลบโดยทางโปรแกรม

  1. นี่คือเมื่อมองเห็น / ติดตั้งมุมมอง

มองเห็นได้

  1. นี่คือเมื่อมุมมองถูกซ่อน / ไม่ได้ติดตั้ง

มุมมองถูกซ่อน / ลบ


1

นี่เป็นอีกโซลูชันของฉันที่ใช้ข้อ จำกัด ระดับความสำคัญ แนวคิดถูกตั้งค่าความกว้างเป็น 0

  1. สร้างมุมมองภาชนะ (สีส้ม) และตั้งค่าความกว้าง ป้อนคำอธิบายรูปภาพที่นี่

  2. สร้างมุมมองเนื้อหา (สีแดง) และตั้งค่าพื้นที่การติดตาม 10pt เป็น superview (สีส้ม) สังเกตเห็นข้อ จำกัด ของพื้นที่ต่อท้ายมี 2 ข้อ จำกัด ต่อท้ายที่มีลำดับความสำคัญแตกต่างกัน ต่ำ (= 10) และสูง (<= 10) นี่เป็นสิ่งสำคัญที่จะหลีกเลี่ยงความกำกวม ป้อนคำอธิบายรูปภาพที่นี่

  3. ตั้งค่าความกว้างของมุมมองสีส้มเป็น 0 เพื่อซ่อนมุมมอง ป้อนคำอธิบายรูปภาพที่นี่


0

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

นี่เป็นตัวอย่างการใช้ ReactiveCocoa:

RACSignal* isViewOneHiddenSignal = RACObserve(self.viewModel, isViewOneHidden);
RACSignal* isViewTwoHiddenSignal = RACObserve(self.viewModel, isViewTwoHidden);
RACSignal* isViewThreeHiddenSignal = RACObserve(self.viewModel, isViewThreeHidden);
RAC(self.viewOne, hidden) = isViewOneHiddenSignal;
RAC(self.viewTwo, hidden) = isViewTwoHiddenSignal;
RAC(self.viewThree, hidden) = isViewThreeHiddenSignal;

RAC(self.viewFourBottomConstraint, priority) = [[[[RACSignal
    combineLatest:@[isViewOneHiddenSignal,
                    isViewTwoHiddenSignal,
                    isViewThreeHiddenSignal]]
    and]
    distinctUntilChanged]
    map:^id(NSNumber* allAreHidden) {
        return [allAreHidden boolValue] ? @(780) : @(UILayoutPriorityDefaultHigh);
    }];

RACSignal* updateFramesSignal = [RACObserve(self.viewFourBottomConstraint, priority) distinctUntilChanged];
[updateFramesSignal
    subscribeNext:^(id x) {
        @strongify(self);
        [self.view setNeedsUpdateConstraints];
        [UIView animateWithDuration:0.3 animations:^{
            [self.view layoutIfNeeded];
        }];
    }];

0

ในกรณีนี้ช่วยใครบางคนฉันสร้างคลาสผู้ช่วยสำหรับการใช้ข้อ จำกัดรูปแบบภาพ ฉันใช้มันในแอปปัจจุบันของฉัน

AutolayoutHelper

อาจปรับให้เหมาะกับความต้องการของฉัน แต่คุณอาจพบว่ามีประโยชน์หรือคุณอาจต้องการแก้ไขและสร้างผู้ช่วยของคุณเอง

ผมต้องขอขอบคุณทิมเขาคำตอบข้างต้นนี้คำตอบเกี่ยวกับ UIScrollViewและยังนี้กวดวิชา


0

นี่คือวิธีที่ฉันจะจัดแนว uiviews ของฉันเพื่อให้ได้โซลูชันของคุณ:

  1. ลากหนึ่ง UIImageView ที่หนึ่งแล้ววางไปทางซ้าย
  2. ลากหนึ่งวาง UIView แล้ววางไว้ที่ด้านขวาของ UIImageView
  3. ลากวาง UILabels สองอันภายใน UIView ที่มีข้อ จำกัด การนำหน้าและต่อท้ายเป็นศูนย์
  4. ตั้งค่าข้อ จำกัด การนำหน้าของ UIView ที่มี 2 ป้ายกำกับเพื่อกำกับดูแลแทน UIImagView
  5. หาก UIImageView ถูกซ่อนอยู่ให้ตั้งค่าคงที่ข้อ จำกัด นำหน้าเป็น 10 px เป็น superview ELSE ตั้งค่าข้อ จำกัด การนำหน้าเป็น 10 px + UIImageView.width + 10 px

ฉันสร้างกฎง่ายๆของฉันเอง เมื่อใดก็ตามที่คุณต้องซ่อน / แสดง uiview ใด ๆ ที่มีข้อ จำกัด อาจได้รับผลกระทบให้เพิ่มการสัมภาษณ์ย่อย / ที่ได้รับผลกระทบทั้งหมดภายใน uiview และอัปเดตค่าคงที่ข้อ จำกัด การนำหน้า / ท้าย / บน / ล่างโดยทางโปรแกรม


0

นี่เป็นคำถามเก่า แต่ฉันหวังว่ามันจะช่วยได้ มาจาก Android ในแพลตฟอร์มนี้คุณมีวิธีการที่สะดวกisVisibleซ่อนมันจากมุมมอง แต่ยังไม่มีเฟรมที่พิจารณาเมื่อ autolayout วาดมุมมอง

ใช้ส่วนขยายและ "ขยาย" uiview คุณสามารถทำหน้าที่คล้ายกันใน iOS (ไม่แน่ใจว่าทำไมมันไม่ได้อยู่ใน UIKit แล้ว) ที่นี่การใช้งานใน swift 3:

    func isVisible(_ isVisible: Bool) {
        self.isHidden = !isVisible
        self.translatesAutoresizingMaskIntoConstraints = isVisible
        if isVisible { //if visible we remove the hight constraint 
            if let constraint = (self.constraints.filter{$0.firstAttribute == .height}.first){
                self.removeConstraint(constraint)
            }
        } else { //if not visible we add a constraint to force the view to have a hight set to 0
            let height = NSLayoutConstraint(item: self, attribute: .height, relatedBy: .equal , toItem: nil, attribute: .notAnAttribute, multiplier: 0, constant: 0)
            self.addConstraint(height)
        }
        self.layoutIfNeeded()
    }

0

วิธีที่เหมาะสมในการทำคือปิดการใช้งานข้อ จำกัด ด้วย isActive = false อย่างไรก็ตามโปรดทราบว่าการปิดการใช้งานข้อ จำกัด จะเป็นการลบและเผยแพร่ดังนั้นคุณจะต้องมีช่องทางที่แข็งแกร่งสำหรับพวกเขา


0

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


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