วิธีเพิ่มข้อ จำกัด แบบโปรแกรมโดยใช้ Swift


448

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

var new_view:UIView! = UIView(frame: CGRectMake(0, 0, 100, 100));
new_view.backgroundColor = UIColor.redColor();
view.addSubview(new_view);

var constX:NSLayoutConstraint = NSLayoutConstraint(item: new_view, attribute: NSLayoutAttribute.CenterX, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.CenterX, multiplier: 1, constant: 0);
self.view.addConstraint(constX);

var constY:NSLayoutConstraint = NSLayoutConstraint(item: new_view, attribute: NSLayoutAttribute.CenterY, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.CenterY, multiplier: 1, constant: 0);
self.view.addConstraint(constY);

var constW:NSLayoutConstraint = NSLayoutConstraint(item: new_view, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: new_view, attribute: NSLayoutAttribute.Width, multiplier: 1, constant: 0);
self.view.addConstraint(constW);

var constH:NSLayoutConstraint = NSLayoutConstraint(item: new_view, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: new_view, attribute: NSLayoutAttribute.Height, multiplier: 1, constant: 0);
self.view.addConstraint(constH);

แต่ Xcode ส่งคืนผลลัพธ์ที่ประหลาดนี้:

2014-10-03 09:48:12.657 Test[35088:2454916] Unable to simultaneously satisfy constraints.  Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
"<NSLayoutConstraint:0x7fa4ea446830 UIView:0x7fa4ea429290.centerX == UIView:0x7fa4ea4470f0.centerX>",
"<NSAutoresizingMaskLayoutConstraint:0x7fa4ea4516c0 h=--& v=--& UIView:0x7fa4ea429290.midX == + 50>",
"<NSLayoutConstraint:0x7fa4ea452830 'UIView-Encapsulated-Layout-Width' H:[UIView:0x7fa4ea4470f0(375)]>",
"<NSAutoresizingMaskLayoutConstraint:0x7fa4ea446db0 h=-&- v=-&- 'UIView-Encapsulated-Layout-Left' H:|-(0)-[UIView:0x7fa4ea4470f0]   (Names: '|':UIWindow:0x7fa4ea444b20 )>"
)

Will attempt to recover by breaking constraint <NSLayoutConstraint:0x7fa4ea446830 UIView:0x7fa4ea429290.centerX == UIView:0x7fa4ea4470f0.centerX>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger. The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in
<UIKit/UIView.h> may also be helpful.

2014-10-03 09:48:12.658 Test[35088:2454916] Unable to simultaneously satisfy constraints.  Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints)
(
"<NSLayoutConstraint:0x7fa4ea44d160 UIView:0x7fa4ea429290.centerY == UIView:0x7fa4ea4470f0.centerY>",
"<NSAutoresizingMaskLayoutConstraint:0x7fa4ea451b30 h=--& v=--& UIView:0x7fa4ea429290.midY == + 50>",
"<NSLayoutConstraint:0x7fa4ea44cf00 'UIView-Encapsulated-Layout-Height' V:[UIView:0x7fa4ea4470f0(667)]>",
"<NSAutoresizingMaskLayoutConstraint:0x7fa4ea452700 h=-&- v=-&- 'UIView-Encapsulated-Layout-Top' V:|-(0)-[UIView:0x7fa4ea4470f0]  (Names: '|':UIWindow:0x7fa4ea444b20 )>"
)

Will attempt to recover by breaking constraint <NSLayoutConstraint:0x7fa4ea44d160 UIView:0x7fa4ea429290.centerY == UIView:0x7fa4ea4470f0.centerY>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger. The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.

คุณสามารถช่วยฉันได้ไหม? ขอบคุณมาก


1
โปรดวางข้อความแสดงข้อผิดพลาดเป็นบล็อกรหัสไม่ใช่ข้อความที่ยกมา >ซึ่งหมายความว่าคุณจะต้องใส่สี่ช่องว่างที่จุดเริ่มต้นของแต่ละบรรทัดที่ไม่ได้เป็น คราวนี้ฉันได้ซ่อมให้คุณแล้ว
rob mayoff

8
คุณหายไป "translateAutoresizingMaskIntoConstraints = false"
Christian 'fuzi' Orgler

1
คุณอาจต้องการใช้ไลบรารี่ที่ยอดเยี่ยมสำหรับข้อ จำกัด แบบไดนามิกและเรียบง่าย github.com/SnapKit/SnapKit
Aashish

ตรวจสอบให้แน่ใจว่าคุณเห็นบน iOS สิ่งที่เป็นความแตกต่างระหว่างอัตรากำไรขั้นต้นขุ่นขอบขุ่นเนื้อหา rects จัดตำแหน่งขอบรูปแบบเบรก มันจะปรับปรุงการตัดสินใจของคุณระหว่างขอบเบรก layoutguides ...
น้ำผึ้ง

นี่คือโพสต์ที่จะอธิบายวิธีเพิ่มข้อ จำกัด ผ่านโค้ด: slicode.com/…
Shankar BS

คำตอบ:


1057

คุณวางแผนที่จะมีการยกกำลังสองUIViewของความกว้าง: 100และความสูง: 100ศูนย์กลางภายในUIViewของUIViewController? หากเป็นเช่นนั้นคุณอาจลองใช้หนึ่งใน 6 รูปแบบต่อไปนี้ของเค้าโครงอัตโนมัติ (Swift 5 / iOS 12.2):


1. การใช้NSLayoutConstraintinitializer

override func viewDidLoad() {
    let newView = UIView()
    newView.backgroundColor = UIColor.red
    view.addSubview(newView)

    newView.translatesAutoresizingMaskIntoConstraints = false
    let horizontalConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.centerX, relatedBy: NSLayoutConstraint.Relation.equal, toItem: view, attribute: NSLayoutConstraint.Attribute.centerX, multiplier: 1, constant: 0)
    let verticalConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.centerY, relatedBy: NSLayoutConstraint.Relation.equal, toItem: view, attribute: NSLayoutConstraint.Attribute.centerY, multiplier: 1, constant: 0)
    let widthConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.width, relatedBy: NSLayoutConstraint.Relation.equal, toItem: nil, attribute: NSLayoutConstraint.Attribute.notAnAttribute, multiplier: 1, constant: 100)
    let heightConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.height, relatedBy: NSLayoutConstraint.Relation.equal, toItem: nil, attribute: NSLayoutConstraint.Attribute.notAnAttribute, multiplier: 1, constant: 100)
    view.addConstraints([horizontalConstraint, verticalConstraint, widthConstraint, heightConstraint])
}
override func viewDidLoad() {
    let newView = UIView()
    newView.backgroundColor = UIColor.red
    view.addSubview(newView)

    newView.translatesAutoresizingMaskIntoConstraints = false
    let horizontalConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.centerX, relatedBy: NSLayoutConstraint.Relation.equal, toItem: view, attribute: NSLayoutConstraint.Attribute.centerX, multiplier: 1, constant: 0)
    let verticalConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.centerY, relatedBy: NSLayoutConstraint.Relation.equal, toItem: view, attribute: NSLayoutConstraint.Attribute.centerY, multiplier: 1, constant: 0)
    let widthConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.width, relatedBy: NSLayoutConstraint.Relation.equal, toItem: nil, attribute: NSLayoutConstraint.Attribute.notAnAttribute, multiplier: 1, constant: 100)
    let heightConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.height, relatedBy: NSLayoutConstraint.Relation.equal, toItem: nil, attribute: NSLayoutConstraint.Attribute.notAnAttribute, multiplier: 1, constant: 100)
    NSLayoutConstraint.activate([horizontalConstraint, verticalConstraint, widthConstraint, heightConstraint])
}
override func viewDidLoad() {
    let newView = UIView()
    newView.backgroundColor = UIColor.red
    view.addSubview(newView)

    newView.translatesAutoresizingMaskIntoConstraints = false
    NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.centerX, relatedBy: NSLayoutConstraint.Relation.equal, toItem: view, attribute: NSLayoutConstraint.Attribute.centerX, multiplier: 1, constant: 0).isActive = true
    NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.centerY, relatedBy: NSLayoutConstraint.Relation.equal, toItem: view, attribute: NSLayoutConstraint.Attribute.centerY, multiplier: 1, constant: 0).isActive = true
    NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.width, relatedBy: NSLayoutConstraint.Relation.equal, toItem: nil, attribute: NSLayoutConstraint.Attribute.notAnAttribute, multiplier: 1, constant: 100).isActive = true
    NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.height, relatedBy: NSLayoutConstraint.Relation.equal, toItem: nil, attribute: NSLayoutConstraint.Attribute.notAnAttribute, multiplier: 1, constant: 100).isActive = true
}

2. ใช้ภาษารูปแบบภาพ

override func viewDidLoad() {
    let newView = UIView()
    newView.backgroundColor = UIColor.red
    view.addSubview(newView)

    newView.translatesAutoresizingMaskIntoConstraints = false
    let views = ["view": view!, "newView": newView]
    let horizontalConstraints = NSLayoutConstraint.constraints(withVisualFormat: "H:[view]-(<=0)-[newView(100)]", options: NSLayoutConstraint.FormatOptions.alignAllCenterY, metrics: nil, views: views)
    let verticalConstraints = NSLayoutConstraint.constraints(withVisualFormat: "V:[view]-(<=0)-[newView(100)]", options: NSLayoutConstraint.FormatOptions.alignAllCenterX, metrics: nil, views: views)
    view.addConstraints(horizontalConstraints)
    view.addConstraints(verticalConstraints)
}
override func viewDidLoad() {
    let newView = UIView()
    newView.backgroundColor = UIColor.red
    view.addSubview(newView)

    newView.translatesAutoresizingMaskIntoConstraints = false
    let views = ["view": view!, "newView": newView]
    let horizontalConstraints = NSLayoutConstraint.constraints(withVisualFormat: "H:[view]-(<=0)-[newView(100)]", options: NSLayoutConstraint.FormatOptions.alignAllCenterY, metrics: nil, views: views)
    let verticalConstraints = NSLayoutConstraint.constraints(withVisualFormat: "V:[view]-(<=0)-[newView(100)]", options: NSLayoutConstraint.FormatOptions.alignAllCenterX, metrics: nil, views: views)
    NSLayoutConstraint.activate(horizontalConstraints)
    NSLayoutConstraint.activate(verticalConstraints)
}

3. การใช้การผสมผสานระหว่างNSLayoutConstraintinitializer และ Visual Format Language

override func viewDidLoad() {
    let newView = UIView()
    newView.backgroundColor = UIColor.red
    view.addSubview(newView)

    newView.translatesAutoresizingMaskIntoConstraints = false
    let views = ["newView": newView]
    let widthConstraints = NSLayoutConstraint.constraints(withVisualFormat: "H:[newView(100)]", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: views)
    let heightConstraints = NSLayoutConstraint.constraints(withVisualFormat: "V:[newView(100)]", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: views)
    let horizontalConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.centerX, relatedBy: NSLayoutConstraint.Relation.equal, toItem: view, attribute: NSLayoutConstraint.Attribute.centerX, multiplier: 1, constant: 0)
    let verticalConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.centerY, relatedBy: NSLayoutConstraint.Relation.equal, toItem: view, attribute: NSLayoutConstraint.Attribute.centerY, multiplier: 1, constant: 0)
    view.addConstraints(widthConstraints)
    view.addConstraints(heightConstraints)
    view.addConstraints([horizontalConstraint, verticalConstraint])
}
override func viewDidLoad() {
    let newView = UIView()
    newView.backgroundColor = UIColor.red
    view.addSubview(newView)

    newView.translatesAutoresizingMaskIntoConstraints = false
    let views = ["newView": newView]
    let widthConstraints = NSLayoutConstraint.constraints(withVisualFormat: "H:[newView(100)]", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: views)
    let heightConstraints = NSLayoutConstraint.constraints(withVisualFormat: "V:[newView(100)]", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: views)
    let horizontalConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.centerX, relatedBy: NSLayoutConstraint.Relation.equal, toItem: view, attribute: NSLayoutConstraint.Attribute.centerX, multiplier: 1, constant: 0)
    let verticalConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.centerY, relatedBy: NSLayoutConstraint.Relation.equal, toItem: view, attribute: NSLayoutConstraint.Attribute.centerY, multiplier: 1, constant: 0)
    NSLayoutConstraint.activate(widthConstraints)
    NSLayoutConstraint.activate(heightConstraints)
    NSLayoutConstraint.activate([horizontalConstraint, verticalConstraint])
}
override func viewDidLoad() {
    let newView = UIView()
    newView.backgroundColor = UIColor.red
    view.addSubview(newView)

    newView.translatesAutoresizingMaskIntoConstraints = false
    let views = ["newView": newView]
    let widthConstraints = NSLayoutConstraint.constraints(withVisualFormat: "H:[newView(100)]", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: views)
    let heightConstraints = NSLayoutConstraint.constraints(withVisualFormat: "V:[newView(100)]", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: views)
    NSLayoutConstraint.activate(widthConstraints)
    NSLayoutConstraint.activate(heightConstraints)
    NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.centerX, relatedBy: NSLayoutConstraint.Relation.equal, toItem: view, attribute: NSLayoutConstraint.Attribute.centerX, multiplier: 1, constant: 0).isActive = true
    NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.centerY, relatedBy: NSLayoutConstraint.Relation.equal, toItem: view, attribute: NSLayoutConstraint.Attribute.centerY, multiplier: 1, constant: 0).isActive = true
}

4. การใช้ UIView.AutoresizingMask

หมายเหตุ: Springs และ Struts จะถูกแปลเป็นข้อ จำกัด ของเลย์เอาต์อัตโนมัติที่รันไทม์

override func viewDidLoad() {
    let newView = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
    newView.backgroundColor = UIColor.red
    view.addSubview(newView)

    newView.translatesAutoresizingMaskIntoConstraints = true
    newView.center = CGPoint(x: view.bounds.midX, y: view.bounds.midY)
    newView.autoresizingMask = [UIView.AutoresizingMask.flexibleLeftMargin, UIView.AutoresizingMask.flexibleRightMargin, UIView.AutoresizingMask.flexibleTopMargin, UIView.AutoresizingMask.flexibleBottomMargin]
}

5. การใช้ NSLayoutAnchor

override func viewDidLoad() {
    let newView = UIView()
    newView.backgroundColor = UIColor.red
    view.addSubview(newView)

    newView.translatesAutoresizingMaskIntoConstraints = false
    let horizontalConstraint = newView.centerXAnchor.constraint(equalTo: view.centerXAnchor)
    let verticalConstraint = newView.centerYAnchor.constraint(equalTo: view.centerYAnchor)
    let widthConstraint = newView.widthAnchor.constraint(equalToConstant: 100)
    let heightConstraint = newView.heightAnchor.constraint(equalToConstant: 100)
    view.addConstraints([horizontalConstraint, verticalConstraint, widthConstraint, heightConstraint])
}
override func viewDidLoad() {
    let newView = UIView()
    newView.backgroundColor = UIColor.red
    view.addSubview(newView)

    newView.translatesAutoresizingMaskIntoConstraints = false
    let horizontalConstraint = newView.centerXAnchor.constraint(equalTo: view.centerXAnchor)
    let verticalConstraint = newView.centerYAnchor.constraint(equalTo: view.centerYAnchor)
    let widthConstraint = newView.widthAnchor.constraint(equalToConstant: 100)
    let heightConstraint = newView.heightAnchor.constraint(equalToConstant: 100)
    NSLayoutConstraint.activate([horizontalConstraint, verticalConstraint, widthConstraint, heightConstraint])
}
override func viewDidLoad() {
    let newView = UIView()
    newView.backgroundColor = UIColor.red
    view.addSubview(newView)

    newView.translatesAutoresizingMaskIntoConstraints = false
    newView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
    newView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
    newView.widthAnchor.constraint(equalToConstant: 100).isActive = true
    newView.heightAnchor.constraint(equalToConstant: 100).isActive = true
}

6. การใช้intrinsicContentSizeและNSLayoutAnchor

import UIKit

class CustomView: UIView {

    override var intrinsicContentSize: CGSize {
        return CGSize(width: 100, height: 100)
    }

}

class ViewController: UIViewController {

    override func viewDidLoad() {
        let newView = CustomView()
        newView.backgroundColor = UIColor.red
        view.addSubview(newView)

        newView.translatesAutoresizingMaskIntoConstraints = false
        let horizontalConstraint = newView.centerXAnchor.constraint(equalTo: view.centerXAnchor)
        let verticalConstraint = newView.centerYAnchor.constraint(equalTo: view.centerYAnchor)
        NSLayoutConstraint.activate([horizontalConstraint, verticalConstraint])
    }

}

ผลลัพธ์:

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


3
มีวิธีใดที่จะทำให้ข้อ จำกัด ลักษณะสมอเคลื่อนไหวได้หรือไม่?
Liumx31

5
ฉันไม่รู้เกี่ยวกับตัวเลือก 5 / สมอสไตล์ฉันชอบมันมากเพราะมันเข้ากับรูปแบบที่ฉันพยายามจะทำ แต่เนื่องจากฉันไม่ได้มีแนวโน้มที่จะปรับปรุงข้อ จำกัด หลังจากที่เพิ่มเข้ามาฉันใช้ชวเลขที่เปิดใช้งานพวกเขาในเวลาเดียวกันกับการสร้างพวกเขาเช่นnewView.centerXAnchor.constraintEqualToAnchor(view.centerXAnchor).active = true
MathewS

ถ้าคุณต้องการออฟเซ็ตให้ใช้ตัวอย่างนี้ให้ h = newView.centerXAnchor.constraintEqualToAnchor (view.centerXAnchor ค่าคงที่: 80) หรือให้ w = updatesAvailablePopover.centerYAnchor.constraintEqualToAnchor (ค่าคงที่: 100)
DogCoffee

1
@ JoeHuang ไม่มือสั้นไม่ทำงานถ้าคุณต้องการเปลี่ยนข้อ จำกัด ในอนาคตเพราะการจดชวเลขกำลังสร้างข้อ จำกัด ใหม่ คุณจะต้องใช้รูปแบบสมอที่ Imanou ใช้ในคำตอบหากคุณต้องการการอ้างอิงเพื่อปรับปรุงข้อ จำกัด ในอนาคต :)
MathewS

1
อย่าลืมnewView.translatesAutoresizingMaskIntoConstraints = falseส่วน! ที่ฉันใช้เวลาสักครู่เพื่อดู
เขียนเมื่อ

247

มันช่วยให้ฉันเรียนรู้ด้วยสายตาดังนั้นนี่เป็นคำตอบเพิ่มเติม

รหัสหม้อไอน้ำ

override func viewDidLoad() {
    super.viewDidLoad()

    let myView = UIView()
    myView.backgroundColor = UIColor.blue
    myView.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(myView)

    // Add constraints code here
    // ...
}

ตัวอย่างต่อไปนี้แต่ละตัวอย่างเป็นอิสระต่อกัน

ปักหมุดที่ขอบซ้าย

myView.leading = leadingMargin + 20

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

วิธีที่ 1: สไตล์ Anchor

let margins = view.layoutMarginsGuide
myView.leadingAnchor.constraint(equalTo: margins.leadingAnchor, constant: 20).isActive = true
  • นอกจากนี้จะleadingAnchorยังมีtrailingAnchor, และtopAnchorbottomAnchor

วิธีที่ 2: ลักษณะ NSLayoutConstraint

NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.leading, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.leadingMargin, multiplier: 1.0, constant: 20.0).isActive = true
  • นอกจากนี้จะ.leadingยังมี.trailing, .topและ.bottomและ
  • นอกจากนี้จะ.leadingMarginยังมี.trailingMargin, และ.topMargin.bottomMargin

ตั้งค่าความกว้างและความสูง

width = 200
height = 100

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

วิธีที่ 1: สไตล์ Anchor

myView.widthAnchor.constraint(equalToConstant: 200).isActive = true
myView.heightAnchor.constraint(equalToConstant: 100).isActive = true

วิธีที่ 2: ลักษณะ NSLayoutConstraint

NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 200).isActive = true
NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 100).isActive = true

กึ่งกลางในภาชนะ

myView.centerX = centerX
myView.centerY = centerY

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

วิธีที่ 1: สไตล์ Anchor

myView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
myView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true

วิธีที่ 2: ลักษณะ NSLayoutConstraint

NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.centerX, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.centerX, multiplier: 1, constant: 0).isActive = true
NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.centerY, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.centerY, multiplier: 1, constant: 0).isActive = true

หมายเหตุ

  • สไตล์ Anchor เป็นวิธีที่ต้องการมากกว่า NSLayoutConstraint Style แต่ใช้ได้เฉพาะใน iOS 9 เท่านั้นดังนั้นหากคุณรองรับ iOS 8 คุณควรใช้NSLayoutConstraintStyle
  • ตัวอย่างด้านบนแสดงข้อ จำกัด เพียงหนึ่งหรือสองข้อที่มุ่งเน้น อย่างไรก็ตามเพื่อให้ถูกต้องmyViewในโครงการทดสอบของฉันฉันต้องมีข้อ จำกัด สี่ประการ

อ่านเพิ่มเติม


2
ดีมาก! หนึ่งทราบขนาดเล็กเพียงคนเดียวleadingเมื่อเทียบกับcenterXข้อ จำกัด ควรมีการระบุ
CyberDude

1
@CyberDude ใช่คุณถูกต้อง ฉันต้องการให้ตัวอย่างทั้งหมดข้างต้นเป็นอิสระจากกันไม่ได้เพิ่มข้อ จำกัด ทั้งหมดในมุมมองเดียวกัน ไม่ชัดเจนเท่าที่ฉันจะชอบแม้ว่า
Suragch

คุณได้ทิ้งสิ่งที่จำเป็นaddConstraint()ไว้viewเพื่อที่จะลงทะเบียนเค้าโครงข้อ จำกัด
Martin

@Suragch Awesome;)
Amir Khan

34

หากคุณต้องการเติมเต็มมุมมองของคุณแล้วฉันขอแนะนำวิธี swifty:

    view.translatesAutoresizingMaskIntoConstraints = false
    let attributes: [NSLayoutAttribute] = [.top, .bottom, .right, .left]
    NSLayoutConstraint.activate(attributes.map {
        NSLayoutConstraint(item: view, attribute: $0, relatedBy: .equal, toItem: view.superview, attribute: $0, multiplier: 1, constant: 0)
    })

อื่น ๆ ที่ชาญฉลาดถ้าคุณต้องการข้อ จำกัด ที่ไม่เท่ากันลองดู NSLayoutAnchor ตั้งแต่ iOS 9 บ่อยครั้งที่มันง่ายกว่ามากที่จะอ่านว่าการใช้ NSLayoutConstraint โดยตรง:

    view.translatesAutoresizingMaskIntoConstraints = false
    view.topAnchor.constraint(equalTo: view.superview!.topAnchor).isActive = true
    view.bottomAnchor.constraint(equalTo: view.superview!.bottomAnchor).isActive = true
    view.leadingAnchor.constraint(equalTo: view.superview!.leadingAnchor, constant: 10).isActive = true
    view.trailingAnchor.constraint(equalTo: view.superview!.trailingAnchor, constant: 10).isActive = true

3
ขึ้นอยู่กับช่วงเวลาของวิดีโอ WWDCนี้ โดยทั่วไปแล้วจะไม่มีประสิทธิภาพในการเปิดใช้งานข้อ จำกัด แบบหนึ่งต่อหนึ่งเช่นการทำisActive = trueไม่ใช่ความคิดที่ดีเสมอไป มันเป็นเรื่องที่ดีขึ้นและมากขึ้น performant ให้กลุ่มข้อ จำกัด NSLayoutConstraint.activateที่เกี่ยวข้องเข้าเป็นหนึ่งเดียวและเปิดใช้งานพวกเขาทั้งหมดในครั้งเดียวโดยใช้
ฮั

21

ข้อ จำกัด สำหรับหลายมุมมองในสนามเด็กเล่น

รวดเร็ว 3+

  var yellowView: UIView!
    var redView: UIView!

    override func loadView() {

        // UI

        let view = UIView()
        view.backgroundColor = .white

        yellowView = UIView()
        yellowView.backgroundColor = .yellow
        view.addSubview(yellowView)

        redView = UIView()
        redView.backgroundColor = .red
        view.addSubview(redView)

        // Layout
        redView.translatesAutoresizingMaskIntoConstraints = false
        yellowView.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            yellowView.topAnchor.constraint(equalTo: view.topAnchor, constant: 20),
            yellowView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
            yellowView.widthAnchor.constraint(equalToConstant: 80),
            yellowView.heightAnchor.constraint(equalToConstant: 80),

            redView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -20),
            redView.trailingAnchor.constraint(equalTo: view.trailingAnchor,constant: -20),
            redView.widthAnchor.constraint(equalToConstant: 80),
            redView.heightAnchor.constraint(equalToConstant: 80)
            ])

        self.view = view
    }

ในความคิดของฉันสนามเด็กเล่น xcode เป็นสถานที่ที่ดีที่สุดสำหรับการเรียนรู้การเพิ่มข้อ จำกัด ทางโปรแกรม

ภาพสนามเด็กเล่น


12

ปัญหาดังที่ข้อความแสดงข้อผิดพลาดแนะนำคือคุณมีข้อ จำกัด ประเภทNSAutoresizingMaskLayoutConstraintsที่ขัดแย้งกับข้อ จำกัด ที่ชัดเจนของคุณเนื่องจากnew_view.translatesAutoresizingMaskIntoConstraintsถูกตั้งค่าเป็นจริง

นี่คือการตั้งค่าเริ่มต้นสำหรับมุมมองที่คุณสร้างในรหัส คุณสามารถปิดการใช้งานเช่นนี้:

var new_view:UIView! = UIView(frame: CGRectMake(0, 0, 100, 100))
new_view.translatesAutoresizingMaskIntoConstraints = false

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

new_view.addConstraint(NSLayoutConstraint(
    item:new_view, attribute:NSLayoutAttribute.Width,
    relatedBy:NSLayoutRelation.Equal,
    toItem:nil, attribute:NSLayoutAttribute.NotAnAttribute,
    multiplier:0, constant:100))

(แทนที่ 100 ด้วยความกว้างที่คุณต้องการให้มี)

หากเป้าหมายการปรับใช้ของคุณคือ iOS 9.0 หรือใหม่กว่าคุณสามารถใช้รหัสที่สั้นกว่านี้ได้:

new_view.widthAnchor.constraintEqualToConstant(100).active = true

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

var new_view:UIView! = UIView(frame: CGRectMake(0, 0, 100, 100))
new_view.backgroundColor = UIColor.redColor();
view.addSubview(new_view);

// This is the default setting but be explicit anyway...
new_view.translatesAutoresizingMaskIntoConstraints = true

new_view.autoresizingMask = [ .FlexibleTopMargin, .FlexibleBottomMargin,
    .FlexibleLeftMargin, .FlexibleRightMargin ]

new_view.center = CGPointMake(view.bounds.midX, view.bounds.midY)

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


หาก UIKit ใช้การปรับขนาดอัตโนมัติภายในนั้นสามารถอธิบายพฤติกรรมที่ไม่เหมาะสมของข้อ จำกัด ที่ยึดไว้ในศูนย์ได้หรือไม่ เมื่อฉันจัดระเบียบคอลเลกชันของ UIButtons เป็นคลาสย่อยของ UIview ข้อ จำกัด การยึดดูเหมือนจะทำงานได้ แต่จะไม่ทำงานเมื่อฉันจัดระเบียบมันเป็นฟังก์ชั่นภายในวิวเวอร์ หากคุณสามารถสำรองเวลาที่คุณอาจได้ดูโพสต์นี้ [ stackoverflow.com/questions/40650951/ … ‌ ler-we-can-real-add-any-new-fences -นวล]
Greg

ไม่นั่นไม่ได้อธิบายถึงพฤติกรรมที่ไม่เหมาะสมของรหัสของคุณ
rob mayoff

12

โดยทั่วไปจะเกี่ยวข้องกับ 3 ขั้นตอน

fileprivate func setupName() { 

    lblName.text = "Hello world"

    // Step 1
    lblName.translatesAutoresizingMaskIntoConstraints = false

    //Step 2
    self.view.addSubview(lblName)

    //Step 3
    NSLayoutConstraint.activate([
        lblName.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
        lblName.centerYAnchor.constraint(equalTo: self.view.centerYAnchor)
    ])
}

สิ่งนี้ทำให้ป้ายกำกับ "hello world" อยู่ตรงกลางของหน้าจอ

โปรดดูข้อ จำกัด การเชื่อมโยงอัตโนมัติโดยโปรแกรม


9

อัปเดตสำหรับ Swift 3

import UIKit

class ViewController: UIViewController {

let redView: UIView = {

    let view = UIView()
    view.translatesAutoresizingMaskIntoConstraints = false
    view.backgroundColor = .red
    return view
}()

override func viewDidLoad() {
    super.viewDidLoad()

    setupViews()
    setupAutoLayout()
}

func setupViews() {

    view.backgroundColor = .white
    view.addSubview(redView)
}

func setupAutoLayout() {

    // Available from iOS 9 commonly known as Anchoring System for AutoLayout...
    redView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20).isActive = true
    redView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -20).isActive = true

    redView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
    redView.heightAnchor.constraint(equalToConstant: 300).isActive = true

    // You can also modified above last two lines as follows by commenting above & uncommenting below lines...
    // redView.topAnchor.constraint(equalTo: view.topAnchor, constant: 20).isActive = true
    // redView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
 }
}

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

ประเภทของข้อ จำกัด

 /*
// regular use
1.leftAnchor
2.rightAnchor
3.topAnchor
// intermediate use
4.widthAnchor
5.heightAnchor
6.bottomAnchor
7.centerXAnchor
8.centerYAnchor
// rare use
9.leadingAnchor
10.trailingAnchor
etc. (note: very project to project)
*/

อย่าลืมเพิ่ม youViewName.translatesAutoresizingMaskIntoConstraints = false
iAj

6

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

import UIKit

class ViewController: UIViewController {

override func viewDidLoad() {
super.viewDidLoad()

let myImageView:UIImageView = UIImageView()
myImageView.backgroundColor = UIColor.red
myImageView.image = UIImage(named:"sample_dog")!
myImageView.translatesAutoresizingMaskIntoConstraints = false
myImageView.layer.borderColor = UIColor.red.cgColor
myImageView.layer.borderWidth = 10
self.view.addSubview(myImageView)

view.removeConstraints(view.constraints)


view.addConstraint(NSLayoutConstraint(
item: myImageView,
attribute: .top,
relatedBy: .equal,
toItem: view,
attribute: .top,
multiplier: 1,
constant:100)

)

view.addConstraint(NSLayoutConstraint(
item: myImageView,
attribute: .centerX,
relatedBy: .equal,
toItem: view,
attribute: .centerX,
multiplier: 1,
constant:0)
)

view.addConstraint(NSLayoutConstraint(
item: myImageView,
attribute: .height,
relatedBy: .equal,
toItem: view,
attribute: .width,
multiplier: 0.5,
constant:40))

view.addConstraint(NSLayoutConstraint(
item: myImageView,
attribute: .width,
relatedBy: .equal,
toItem: view,
attribute: .width,
multiplier: 0.5,
constant:40))

}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
}
}

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


4

มันแตกต่างกันเล็กน้อยใน xcode 7.3.1 นี่คือสิ่งที่ฉันเกิดขึ้น

   // creating the view
        let newView = UIView()
        newView.backgroundColor = UIColor.redColor()
        newView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(newView)

        // creating the constraint 

        // attribute and relation cannot be set directyl you need to create a cariable of them
        let layout11 = NSLayoutAttribute.CenterX
        let layout21 = NSLayoutRelation.Equal
        let layout31 = NSLayoutAttribute.CenterY
        let layout41 = NSLayoutAttribute.Width
        let layout51 = NSLayoutAttribute.Height
        let layout61 = NSLayoutAttribute.NotAnAttribute

        // defining all the constraint
        let horizontalConstraint = NSLayoutConstraint(item: newView, attribute: layout11, relatedBy: layout21, toItem: view, attribute: layout11, multiplier: 1, constant: 0)
        let verticalConstraint = NSLayoutConstraint(item: newView, attribute: layout31, relatedBy: layout21, toItem: view, attribute: layout31, multiplier: 1, constant: 0)
        let widthConstraint = NSLayoutConstraint(item: newView, attribute: layout41, relatedBy: layout21, toItem: nil, attribute: layout61, multiplier: 1, constant: 100)
        let heightConstraint = NSLayoutConstraint(item: newView, attribute: layout51, relatedBy: layout21, toItem: nil, attribute: layout61, multiplier: 1, constant: 100)

        // adding all the constraint
        NSLayoutConstraint.activateConstraints([horizontalConstraint,verticalConstraint,widthConstraint,heightConstraint])

translateatesAutoresizingMaskIntoConstraints = false :))
Marin

4

ต้องการเพิ่มแนวคิดเชิงทฤษฎีลงในคำตอบของ Imanou Petit เพื่อให้สามารถเข้าใจวิธีการทำงานของเลย์เอาต์อัตโนมัติ

หากต้องการทำความเข้าใจกับเลย์เอาต์อัตโนมัติให้พิจารณาว่ามุมมองของคุณเป็นวัตถุของยางซึ่งถูกย่อขนาดตั้งแต่แรก

ในการวางวัตถุบนหน้าจอเราจำเป็นต้องมี 4 สิ่ง:

  • พิกัด X ของวัตถุ (ตำแหน่งแนวนอน)

  • พิกัดของวัตถุ Y (ตำแหน่งแนวตั้ง)

  • ความกว้างของวัตถุ

  • ความสูงของวัตถุ

พิกัด 1 X:มีหลายวิธีในการกำหนดพิกัด x ให้กับมุมมอง

เช่นข้อ จำกัด ชั้นนำ, ข้อ จำกัด ต่อท้าย, ศูนย์แนวนอน ฯลฯ

2 พิกัด Y:มีหลายวิธีในการให้พิกัด y กับมุมมอง:

เช่นข้อ จำกัด ด้านบนข้อ จำกัด ด้านล่างศูนย์แนวตั้ง ฯลฯ

3 ความกว้างของวัตถุ:มีสองวิธีในการกำหนดความกว้างให้กับมุมมอง:

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

ข อย่าเพิ่มข้อ จำกัด ด้านความกว้างใด ๆ แต่เพิ่มข้อ จำกัด พิกัด x ที่จุดสิ้นสุดของมุมมองทั้งสองและนำหน้าข้อ จำกัด ทั้งสองนี้จะขยาย / ย่อขนาดวัตถุยางของคุณโดยการดึง / ดันจากปลายทั้งสองด้านนำหน้าและต่อท้าย

4 ความสูงของวัตถุ:คล้ายกับความกว้างมีสองวิธีในการให้ข้อ จำกัด ความสูงกับมุมมองเช่นกัน:

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

ข อย่าเพิ่มข้อจำกัดความสูงใด ๆ แต่เพิ่มข้อ จำกัด พิกัด x ทั้งสองด้านของมุมมองด้านบนและด้านล่างข้อ จำกัด ทั้งสองนี้จะขยาย / หดวัตถุยางของคุณดึง / ดันจากปลายทั้งด้านบนและด้านล่าง


3
    var xCenterConstraint : NSLayoutConstraint!
    var yCenterConstraint: NSLayoutConstraint!

 xCenterConstraint = NSLayoutConstraint(item: self.view, attribute: .CenterX, relatedBy: .Equal, toItem: (Your view NAme), attribute: .CenterX, multiplier: 1, constant: 0)
            self.view.addConstraint(xCenterConstraint)

 yCenterConstraint = NSLayoutConstraint(item: self.view, attribute: .CenterY, relatedBy: .Equal, toItem: (Your view Name), attribute: .CenterY, multiplier: 1, constant: 0)
            self.view.addConstraint(yCenterConstraint)

7
โปรดอธิบายรหัสและวิธีการตอบคำถาม
Ben Rhys-Lewis

3

นี่เป็นวิธีหนึ่งในการเพิ่มข้อ จำกัด ทางโปรแกรม

override func viewDidLoad() {
            super.viewDidLoad()


let myLabel = UILabel()
        myLabel.labelFrameUpdate(label: myLabel, text: "Welcome User", font: UIFont(name: "times new roman", size: 40)!, textColor: UIColor.red, textAlignment: .center, numberOfLines: 0, borderWidth: 2.0, BorderColor: UIColor.red.cgColor)
        self.view.addSubview(myLabel)


         let myLabelhorizontalConstraint = NSLayoutConstraint(item: myLabel, attribute: NSLayoutAttribute.centerX, relatedBy: NSLayoutRelation.equal, toItem: self.view, attribute: NSLayoutAttribute.centerX, multiplier: 1, constant: 0)
        let myLabelverticalConstraint = NSLayoutConstraint(item: myLabel, attribute: NSLayoutAttribute.centerY, relatedBy: NSLayoutRelation.equal, toItem: self.view, attribute: NSLayoutAttribute.centerY, multiplier: 1, constant: 0)
        let mylabelLeading = NSLayoutConstraint(item: myLabel, attribute: NSLayoutAttribute.leading, relatedBy: NSLayoutRelation.equal, toItem: self.view, attribute: NSLayoutAttribute.leading, multiplier: 1, constant: 10)
        let mylabelTrailing = NSLayoutConstraint(item: myLabel, attribute: NSLayoutAttribute.trailing, relatedBy: NSLayoutRelation.equal, toItem: self.view, attribute: NSLayoutAttribute.trailing, multiplier: 1, constant: -10)
        let myLabelheightConstraint = NSLayoutConstraint(item: myLabel, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 50)
        NSLayoutConstraint.activate(\[myLabelhorizontalConstraint, myLabelverticalConstraint, myLabelheightConstraint,mylabelLeading,mylabelTrailing\])
}

extension UILabel
{
    func labelFrameUpdate(label:UILabel,text:String = "This is sample Label",font:UIFont = UIFont(name: "times new roman", size: 20)!,textColor:UIColor = UIColor.red,textAlignment:NSTextAlignment = .center,numberOfLines:Int = 0,borderWidth:CGFloat = 2.0,BorderColor:CGColor = UIColor.red.cgColor){
        label.translatesAutoresizingMaskIntoConstraints = false
        label.text = text
        label.font = font
        label.textColor = textColor
        label.textAlignment = textAlignment
        label.numberOfLines = numberOfLines
        label.layer.borderWidth = borderWidth
        label.layer.borderColor = UIColor.red.cgColor
    }
}

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


2

คุณกำลังเพิ่มข้อ จำกัด ที่กำหนดไว้ทั้งหมดไปself.viewซึ่งเป็นสิ่งที่ผิดเป็นความกว้างและความสูง จำกัด newViewควรจะเพิ่มของคุณ

นอกจากนี้ตามที่ฉันเข้าใจว่าคุณต้องการตั้งค่าความกว้างและความสูงคงที่ 100: 100 ในกรณีนี้คุณควรเปลี่ยนรหัสของคุณเป็น:

var constW = NSLayoutConstraint(item: newView, 
    attribute: .Width, 
    relatedBy: .Equal, 
    toItem: nil, 
    attribute: .NotAnAttribute, 
    multiplier: 1, 
    constant: 100)
newView.addConstraint(constW)

var constH = NSLayoutConstraint(item: newView, 
    attribute: .Height, 
    relatedBy: .Equal, 
    toItem: nil, 
    attribute: .NotAnAttribute, 
    multiplier: 1, 
    constant: 100)
newView.addConstraint(constH)

2

หากพบว่าข้างต้นน่าเกลียด คุณควรพิจารณาใช้ DSL สำหรับข้อ จำกัด เช่นSnapKit ทำให้ API ข้อ จำกัด เป็นมิตรกับผู้ใช้มากขึ้น

view.snp.makeConstraints { make in
    make.edges.equalToSuperview()
}

1

เราสามารถทำสิ่งนี้กับ 5.1 อย่างรวดเร็ว

การตั้งค่า 1

  • subview จัดให้อยู่กึ่งกลาง
  • ตั้งค่าความสูงความกว้างของ subview โดยใช้การลอย

    view.addSubview(myView1)
    myView1.translatesAutoresizingMaskIntoConstraints = false
    NSLayoutConstraint.activate([
        myView1.centerXAnchor.constraint(equalTo: view.centerXAnchor),
        myView1.centerYAnchor.constraint(equalTo: view.centerYAnchor),
        myView1.widthAnchor.constraint(equalToConstant: 100),
        myView1.heightAnchor.constraint(equalToConstant: 100),
    ])

การตั้งค่า 2

  • subview จัดเรียงเพื่อดูส่วนนำและส่วนบนสุด
  • ชุดความกว้างย่อยของมุมมองย่อยโดยใช้ความสูงความกว้างของมุมมอง

        view.addSubview(myView2)
        myView2.translatesAutoresizingMaskIntoConstraints = false
    
        NSLayoutConstraint.activate([
            myView2.leadingAnchor.constraint(equalTo: view.leadingAnchor,constant: 16),
            myView2.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor,constant: 16),
            myView2.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.3),
            myView2.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.3)
        ])

ผลลัพธ์


0

ลองใช้UIViewส่วนขยายที่สวยงามนี้เพื่อดูข้อ จำกัด คุณสามารถทำข้อ จำกัด ได้ง่าย ๆ เช่น:


 - firstView.coverWholeSuperview()
 - firstView.constraints(size: CGSize(width: 44, height: 44), centerX: view.centerXAnchor, centerY: view.centerXAnchor)
 - firstView.constraints(top: view.topAnchor, 
                         leading: secondView.leadingAnchor, 
                         bottom: view.bottomAnchor, 
                         trailing: secondView.trailingAnchor, 
                         padding: UIEdgeInsets(top: 12, left: 12, bottom: 12, right: 12))

นี่คือส่วนขยายเพียงแค่คัดลอกไปยังโครงการของคุณ

extension UIView {
    /// Attaches all sides of the receiver to its parent view
    func coverWholeSuperview(margin: CGFloat = 0.0) {
        let view = superview
        layoutAttachTop(to: view, margin: margin)
        layoutAttachBottom(to: view, margin: margin)
        layoutAttachLeading(to: view, margin: margin)
        layoutAttachTrailing(to: view, margin: margin)

    }

    /// Attaches the top of the current view to the given view's top if it's a superview of the current view
    /// or to it's bottom if it's not (assuming this is then a sibling view).
    @discardableResult
    func layoutAttachTop(to: UIView? = nil, margin: CGFloat = 0.0) -> NSLayoutConstraint {

        let view: UIView? = to ?? superview
        let isSuperview = view == superview
        let constraint = NSLayoutConstraint(item: self, attribute: .top, relatedBy: .equal,
                                            toItem: view, attribute: isSuperview ? .top : .bottom, multiplier: 1.0,
                                            constant: margin)
        superview?.addConstraint(constraint)

        return constraint
    }

    /// Attaches the bottom of the current view to the given view
    @discardableResult
    func layoutAttachBottom(to: UIView? = nil, margin: CGFloat = 0.0, priority: UILayoutPriority? = nil) -> NSLayoutConstraint {

        let view: UIView? = to ?? superview
        let isSuperview = (view == superview) || false
        let constraint = NSLayoutConstraint(item: self, attribute: .bottom, relatedBy: .equal,
                                            toItem: view, attribute: isSuperview ? .bottom : .top, multiplier: 1.0,
                                            constant: -margin)
        if let priority = priority {
            constraint.priority = priority
        }
        superview?.addConstraint(constraint)

        return constraint
    }

    /// Attaches the leading edge of the current view to the given view
    @discardableResult
    func layoutAttachLeading(to: UIView? = nil, margin: CGFloat = 0.0) -> NSLayoutConstraint {

        let view: UIView? = to ?? superview
        let isSuperview = (view == superview) || false
        let constraint = NSLayoutConstraint(item: self, attribute: .leading, relatedBy: .equal,
                                            toItem: view, attribute: isSuperview ? .leading : .trailing, multiplier: 1.0,
                                            constant: margin)
        superview?.addConstraint(constraint)

        return constraint
    }

    /// Attaches the trailing edge of the current view to the given view
    @discardableResult
    func layoutAttachTrailing(to: UIView? = nil, margin: CGFloat = 0.0, priority: UILayoutPriority? = nil) -> NSLayoutConstraint {

        let view: UIView? = to ?? superview
        let isSuperview = (view == superview) || false
        let constraint = NSLayoutConstraint(item: self, attribute: .trailing, relatedBy: .equal,
                                            toItem: view, attribute: isSuperview ? .trailing : .leading, multiplier: 1.0,
                                            constant: -margin)
        if let priority = priority {
            constraint.priority = priority
        }
        superview?.addConstraint(constraint)

        return constraint
    }

    // For anchoring View
    struct AnchoredConstraints {
        var top, leading, bottom, trailing, width, height, centerX, centerY: NSLayoutConstraint?
    }

    @discardableResult
    func constraints(top: NSLayoutYAxisAnchor? = nil, leading: NSLayoutXAxisAnchor? = nil, bottom: NSLayoutYAxisAnchor? = nil,
                trailing: NSLayoutXAxisAnchor? = nil, padding: UIEdgeInsets = .zero, size: CGSize = .zero,
                centerX: NSLayoutXAxisAnchor? = nil, centerY: NSLayoutYAxisAnchor? = nil,
                centerXOffset: CGFloat = 0, centerYOffset: CGFloat = 0) -> AnchoredConstraints {

        translatesAutoresizingMaskIntoConstraints = false
        var anchoredConstraints = AnchoredConstraints()

        if let top = top {
            anchoredConstraints.top = topAnchor.constraint(equalTo: top, constant: padding.top)
        }

        if let leading = leading {
            anchoredConstraints.leading = leadingAnchor.constraint(equalTo: leading, constant: padding.left)
        }

        if let bottom = bottom {
            anchoredConstraints.bottom = bottomAnchor.constraint(equalTo: bottom, constant: -padding.bottom)
        }

        if let trailing = trailing {
            anchoredConstraints.trailing = trailingAnchor.constraint(equalTo: trailing, constant: -padding.right)
        }

        if size.width != 0 {
            anchoredConstraints.width = widthAnchor.constraint(equalToConstant: size.width)
        }

        if size.height != 0 {
            anchoredConstraints.height = heightAnchor.constraint(equalToConstant: size.height)
        }

        if let centerX = centerX {
            anchoredConstraints.centerX = centerXAnchor.constraint(equalTo: centerX, constant: centerXOffset)
        }

        if let centerY = centerY {
            anchoredConstraints.centerY = centerYAnchor.constraint(equalTo: centerY, constant: centerYOffset)
        }

        [anchoredConstraints.top, anchoredConstraints.leading, anchoredConstraints.bottom,
         anchoredConstraints.trailing, anchoredConstraints.width,
         anchoredConstraints.height, anchoredConstraints.centerX,
         anchoredConstraints.centerY].forEach { $0?.isActive = true }

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