การจำลองพฤติกรรมแบบฟิตโดยใช้ข้อ จำกัด AutoLayout ใน Xcode 6


336

ฉันต้องการใช้ AutoLayout เพื่อปรับขนาดและเลย์เอาต์มุมมองในลักษณะที่ทำให้ระลึกถึงโหมดเนื้อหาแบบพอดีของ UIImageView

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

หากอัตราส่วนมุมมองของคอนเทนเนอร์กว้างกว่ามุมมองย่อยฉันต้องการให้ความสูงของมุมมองย่อยเท่ากับความสูงของมุมมองพาเรนต์

หากอัตราส่วนมุมมองของคอนเทนเนอร์สูงกว่ามุมมองย่อยฉันต้องการความกว้างของมุมมองย่อยเท่ากับความกว้างของมุมมองพาเรนต์

ในกรณีใดกรณีหนึ่งฉันต้องการให้มุมมองย่อยจัดกึ่งกลางแนวนอนและแนวตั้งภายในมุมมองคอนเทนเนอร์

มีวิธีใดบ้างที่จะบรรลุเป้าหมายนี้โดยใช้ข้อ จำกัด AutoLayout ใน Xcode 6 หรือในเวอร์ชันก่อนหน้า? เป็นการดีที่จะใช้ตัวสร้างส่วนต่อประสาน แต่ถ้าไม่ใช่ก็เป็นไปได้ที่จะกำหนดข้อ จำกัด ดังกล่าวโดยทางโปรแกรม

คำตอบ:


1046

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

อย่างไรก็ตามคุณสามารถทำได้ด้วยเลย์เอาต์อัตโนมัติ คุณสามารถทำได้ทั้งหมดใน IB ตั้งแต่ Xcode 5.1 เริ่มจากมุมมอง:

บางมุมมอง

มุมมองสีเขียวอ่อนมีอัตราส่วนกว้างยาว 4: 1 มุมมองสีเขียวเข้มมีอัตราส่วนกว้างยาวเท่ากับ 1: 4 ฉันจะตั้งค่าข้อ จำกัด เพื่อให้มุมมองสีฟ้าเติมครึ่งบนของหน้าจอมุมมองสีชมพูจะเติมครึ่งล่างของหน้าจอและมุมมองสีเขียวแต่ละจุดจะขยายให้มากที่สุดเท่าที่จะทำได้ขณะที่ยังคงรักษาอัตราส่วนและความเหมาะสมใน ภาชนะ

ก่อนอื่นฉันจะสร้างข้อ จำกัด ในมุมมองทั้งสี่ด้านของสีน้ำเงิน ฉันจะตรึงมันไว้กับเพื่อนบ้านที่ใกล้ที่สุดของแต่ละขอบด้วยระยะทาง 0 ฉันต้องปิดระยะขอบ:

ข้อ จำกัด สีฟ้า

โปรดทราบว่าฉันยังไม่อัปเดตเฟรม ฉันพบว่าง่ายกว่าที่จะออกจากห้องระหว่างมุมมองเมื่อตั้งค่าข้อ จำกัด และตั้งค่าคงที่เป็น 0 (หรืออะไรก็ตาม) ด้วยมือ

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

ข้อ จำกัด สีชมพู

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

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

ถ้าฉันบอกให้ Xcode อัปเดตเฟรมทั้งหมดฉันจะได้รับ:

วางภาชนะ

ดังนั้นข้อ จำกัด ที่ฉันตั้งขึ้นมานั้นถูกต้องแล้ว ฉันเลิกทำแล้วเริ่มทำงานกับมุมมองสีเขียวอ่อน

การปรับมุมมองมุมมองสีเขียวอ่อนต้องใช้ข้อ จำกัด ห้าประการ:

  • ข้อ จำกัด อัตราส่วนภาพที่จำเป็นสำหรับมุมมองสีเขียวอ่อน คุณสามารถสร้างข้อ จำกัด นี้ใน xib หรือกระดานเรื่องราวด้วย Xcode 5.1 หรือใหม่กว่า
  • ข้อ จำกัด ลำดับความสำคัญที่ต้องการจำกัดความกว้างของมุมมองสีเขียวอ่อนให้น้อยกว่าหรือเท่ากับความกว้างของคอนเทนเนอร์
  • ข้อ จำกัด ที่มีลำดับความสำคัญสูงตั้งค่าความกว้างของมุมมองสีเขียวอ่อนให้เท่ากับความกว้างของคอนเทนเนอร์
  • ข้อ จำกัด ลำดับความสำคัญที่ต้องการ จำกัด ความสูงของมุมมองสีเขียวอ่อนให้น้อยกว่าหรือเท่ากับความสูงของคอนเทนเนอร์
  • ข้อ จำกัด ที่มีลำดับความสำคัญสูงตั้งค่าความสูงของมุมมองสีเขียวอ่อนให้เท่ากับความสูงของคอนเทนเนอร์

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

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

ดังนั้นก่อนอื่นฉันสร้างข้อ จำกัด อัตราส่วนกว้างยาว:

มุมมองด้านบน

จากนั้นฉันสร้างข้อ จำกัด ความกว้างและความสูงเท่ากับคอนเทนเนอร์:

ขนาดเท่ากันด้านบน

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

ด้านบนน้อยกว่าหรือเท่ากับขนาด

ต่อไปฉันต้องสร้างข้อ จำกัด ความกว้างและความสูงเท่ากับชุดอื่นด้วยคอนเทนเนอร์:

ขนาดเท่ากับสูงสุดอีกครั้ง

และฉันต้องการทำให้ข้อ จำกัด ใหม่เหล่านี้น้อยกว่าลำดับความสำคัญที่ต้องการ:

ด้านบนไม่จำเป็นต้องเท่ากัน

ท้ายที่สุดคุณขอให้การย่อยนั้นอยู่กึ่งกลางในคอนเทนเนอร์ดังนั้นฉันจะตั้งค่าข้อ จำกัด เหล่านั้น:

กึ่งกลางด้านบน

ตอนนี้เพื่อทดสอบฉันจะเลือกตัวควบคุมมุมมองและขอให้ Xcode อัปเดตเฟรมทั้งหมด นี่คือสิ่งที่ฉันได้รับ:

เค้าโครงด้านบนไม่ถูกต้อง

อ๊ะ! มุมมองย่อยได้ขยายเพื่อเติมเต็มคอนเทนเนอร์ ถ้าผมเลือกผมจะเห็นว่าในความเป็นจริงมันบำรุงรักษาอัตราส่วนของมัน แต่มันทำ aspect- เติมแทน aspect- พอดี

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

แก้ไขข้อ จำกัด ด้านบน

Xcode อัพเดตเค้าโครง:

เค้าโครงด้านบนที่ถูกต้อง

ตอนนี้ฉันทำสิ่งเดียวกันทั้งหมดกับมุมมองสีเขียวเข้มที่ด้านล่าง ฉันต้องตรวจสอบให้แน่ใจว่าอัตราส่วนภาพคือ 1: 4 (Xcode ปรับขนาดในลักษณะแปลก ๆ เนื่องจากไม่มีข้อ จำกัด ) ฉันจะไม่แสดงขั้นตอนอีกครั้งเนื่องจากมันเหมือนกัน นี่คือผลลัพธ์:

แก้ไขเค้าโครงด้านบนและด้านล่างให้ถูกต้อง

ตอนนี้ฉันสามารถรันมันในเครื่องจำลอง iPhone 4S ซึ่งมีขนาดหน้าจอที่แตกต่างจากการใช้ IB และการหมุนทดสอบ

การทดสอบ iPhone 4s

และฉันสามารถทดสอบในเครื่องจำลอง iPhone 6:

การทดสอบ iPhone 6

ฉันได้อัปโหลดกระดานเรื่องราวสุดท้ายของฉันไปยังส่วนสำคัญนี้เพื่อความสะดวกของคุณ


27
ผมใช้LICEcap ได้ฟรี (GPL) และบันทึกโดยตรงไปยัง GIF ตราบใดที่ GIF เคลื่อนไหวมีขนาดไม่เกิน 2 MB คุณสามารถโพสต์ลงในเว็บไซต์นี้ได้เหมือนกับภาพอื่น ๆ
rob mayoff

1
@LucaTorella ด้วยข้อ จำกัด ที่มีลำดับความสำคัญสูงเท่านั้นโครงร่างจึงไม่ชัดเจน เพียงเพราะมันได้รับผลลัพธ์ที่คุณต้องการในวันนี้ไม่ได้หมายความว่ามันจะอยู่ใน iOS เวอร์ชั่นถัดไป สมมติว่า subview ต้องการอัตราส่วนกว้างยาว 1: 1, superview คือขนาด 99 × 100 และคุณมีอัตราส่วนกว้างยาวและข้อ จำกัด ด้านความเท่าเทียมกันที่มีความสำคัญสูงเท่านั้น จากนั้นเลย์เอาต์อัตโนมัติสามารถตั้งค่ามุมมองย่อยเป็น 99 × 99 (มีข้อผิดพลาดทั้งหมด 1) หรือขนาด 100 × 100 (พร้อมข้อผิดพลาดทั้งหมด 1) ขนาดเดียวคือปรับให้พอดี อีกอันคือการเติมภาพ การเพิ่มข้อ จำกัด ที่จำเป็นต้องสร้างวิธีแก้ไขข้อผิดพลาดน้อยที่สุดที่ไม่ซ้ำกัน
rob mayoff

1
@LucaTorella ขอบคุณสำหรับการแก้ไขเกี่ยวกับความพร้อมใช้งานของข้อ จำกัด อัตราส่วนภาพ
rob mayoff

11
แอพที่ดีกว่า 10,000 แอพพร้อมโพสต์เดียว ... เหลือเชื่อ
DonVaughn

2
ว้าว .. คำตอบที่ดีที่สุดที่นี่ในสแต็คล้นฉันเคยเห็นมา .. ขอบคุณสำหรับเซอร์นี้ ..
0yeoj

24

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

AspectFitView.h :

#import <UIKit/UIKit.h>

@interface AspectFitView : UIView

@property (nonatomic, strong) UIView *childView;

@end

AspectFitView.m :

#import "AspectFitView.h"

@implementation AspectFitView

- (void)setChildView:(UIView *)childView
{
    if (_childView) {
        [_childView removeFromSuperview];
    }

    _childView = childView;

    [self addSubview:childView];
    [self setNeedsLayout];
}

- (void)layoutSubviews
{
    [super layoutSubviews];

    if (_childView) {
        CGSize childSize = _childView.frame.size;
        CGSize parentSize = self.frame.size;
        CGFloat aspectRatioForHeight = childSize.width / childSize.height;
        CGFloat aspectRatioForWidth = childSize.height / childSize.width;

        if ((parentSize.height * aspectRatioForHeight) > parentSize.height) {
            // whole height, adjust width
            CGFloat width = parentSize.width * aspectRatioForWidth;
            _childView.frame = CGRectMake((parentSize.width - width) / 2.0, 0, width, parentSize.height);
        } else {
            // whole width, adjust height
            CGFloat height = parentSize.height * aspectRatioForHeight;
            _childView.frame = CGRectMake(0, (parentSize.height - height) / 2.0, parentSize.width, height);
        }
    }
}

@end

ถัดไปคุณเปลี่ยนคลาสของมุมมองสีน้ำเงินและสีชมพูในกระดานเรื่องราวเป็นAspectFitViews ในที่สุดคุณตั้งสองร้านไป ViewController ของคุณtopAspectFitViewและbottomAspectFitViewและการตั้งค่าของพวกเขาchildViewในviewDidLoad:

- (void)viewDidLoad {
    [super viewDidLoad];

    UIView *top = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 100)];
    top.backgroundColor = [UIColor lightGrayColor];

    UIView *bottom = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 500)];
    bottom.backgroundColor = [UIColor greenColor];

    _topAspectFitView.childView = top;
    _bottomAspectFitView.childView = bottom;
}

ดังนั้นจึงไม่ยากที่จะทำในโค้ดและยังสามารถปรับได้มากและทำงานกับมุมมองที่มีขนาดต่างกันและอัตราส่วนภาพที่แตกต่างกัน

อัปเดตกรกฎาคม 2558 : ค้นหาแอปตัวอย่างที่นี่: https://github.com/jfahrenkrug/SPWKAspectFitView


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

1
มีประโยชน์มากที่จะมีโปรแกรมอ้างอิงเช่นกัน
ctpenrose

@JohannesFahrenkrug หากคุณมีโครงการสอนคุณสามารถแบ่งปันได้หรือไม่ ขอบคุณ :)
Erhan Demirci

1
@ErhanDemirci แน่นอน, ไปเลย: github.com/jfahrenkrug/SPWKAspectFitView
Johannes Fahrenkrug

8

ฉันต้องการโซลูชันจากคำตอบที่ยอมรับ แต่ดำเนินการจากโค้ด วิธีที่สง่างามที่สุดที่ผมเคยพบก็คือการใช้กรอบการก่ออิฐ

#import "Masonry.h"

...

[view mas_makeConstraints:^(MASConstraintMaker *make) {
    make.width.equalTo(view.mas_height).multipliedBy(aspectRatio);
    make.size.lessThanOrEqualTo(superview);
    make.size.equalTo(superview).with.priorityHigh();
    make.center.equalTo(superview);
}];

5

นี่สำหรับ macOS

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

โดยทั่วไปให้เพิ่มช่องว่างนำหน้าสองช่องโดยที่หนึ่งคือ> = 0 @ 1,000 ลำดับความสำคัญที่ต้องการและอีกช่องว่างหนึ่งคือ = 0 @ 250 ลำดับความสำคัญต่ำ ทำการตั้งค่าแบบเดียวกันกับการติดตามพื้นที่บนและล่าง

แน่นอนคุณต้องกำหนดอัตราส่วนภาพและศูนย์ X และศูนย์ Y

แล้วงานก็เสร็จ!

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


คุณจะทำอย่างไรกับการเขียนโปรแกรมแบบนี้?
FateNuller

@FateNuller เพียงทำตามขั้นตอนหรือไม่
brianLikeApple

4

ฉันพบว่าตัวเองต้องการพฤติกรรมที่เต็มไปด้วยเพื่อที่ UIImageView จะรักษาอัตราส่วนของตัวเองและเติมมุมมองภาชนะทั้งหมด พลุกพล่าน UIImageView ของฉันทำลายข้อ จำกัด ทั้งความกว้างและความสูงเท่ากัน (อธิบายไว้ในคำตอบของ Rob) และการแสดงผลที่ความละเอียดเต็ม

วิธีการแก้ปัญหาคือการตั้งค่าลำดับความต้านทานการบีบอัดเนื้อหาของ UIImageView ที่ต่ำกว่าลำดับความสำคัญของข้อ จำกัด ที่มีความกว้างและความสูงเท่ากัน:

ความต้านทานการบีบอัดเนื้อหา


2

นี่คือพอร์ตของคำตอบที่ยอดเยี่ยมของ @ rob_mayoff สำหรับวิธีการใช้รหัสเป็นศูนย์กลางโดยใช้NSLayoutAnchorวัตถุและส่งไปยัง Xamarin สำหรับฉันNSLayoutAnchorและคลาสที่เกี่ยวข้องทำให้ AutoLayout เป็นโปรแกรมที่ง่ายขึ้นมาก:

public class ContentView : UIView
{
        public ContentView (UIColor fillColor)
        {
            BackgroundColor = fillColor;
        }
}

public class MyController : UIViewController 
{
    public override void ViewDidLoad ()
    {
        base.ViewDidLoad ();

        //Starting point:
        var view = new ContentView (UIColor.White);

        blueView = new ContentView (UIColor.FromRGB (166, 200, 255));
        view.AddSubview (blueView);

        lightGreenView = new ContentView (UIColor.FromRGB (200, 255, 220));
        lightGreenView.Frame = new CGRect (20, 40, 200, 60);

        view.AddSubview (lightGreenView);

        pinkView = new ContentView (UIColor.FromRGB (255, 204, 240));
        view.AddSubview (pinkView);

        greenView = new ContentView (UIColor.Green);
        greenView.Frame = new CGRect (80, 20, 40, 200);
        pinkView.AddSubview (greenView);

        //Now start doing in code the things that @rob_mayoff did in IB

        //Make the blue view size up to its parent, but half the height
        blueView.TranslatesAutoresizingMaskIntoConstraints = false;
        var blueConstraints = new []
        {
            blueView.LeadingAnchor.ConstraintEqualTo(view.LayoutMarginsGuide.LeadingAnchor),
            blueView.TrailingAnchor.ConstraintEqualTo(view.LayoutMarginsGuide.TrailingAnchor),
            blueView.TopAnchor.ConstraintEqualTo(view.LayoutMarginsGuide.TopAnchor),
            blueView.HeightAnchor.ConstraintEqualTo(view.LayoutMarginsGuide.HeightAnchor, (nfloat) 0.5)
        };
        NSLayoutConstraint.ActivateConstraints (blueConstraints);

        //Make the pink view same size as blue view, and linked to bottom of blue view
        pinkView.TranslatesAutoresizingMaskIntoConstraints = false;
        var pinkConstraints = new []
        {
            pinkView.LeadingAnchor.ConstraintEqualTo(blueView.LeadingAnchor),
            pinkView.TrailingAnchor.ConstraintEqualTo(blueView.TrailingAnchor),
            pinkView.HeightAnchor.ConstraintEqualTo(blueView.HeightAnchor),
            pinkView.TopAnchor.ConstraintEqualTo(blueView.BottomAnchor)
        };
        NSLayoutConstraint.ActivateConstraints (pinkConstraints);


        //From here, address the aspect-fitting challenge:

        lightGreenView.TranslatesAutoresizingMaskIntoConstraints = false;
        //These are the must-fulfill constraints: 
        var lightGreenConstraints = new []
        {
            //Aspect ratio of 1 : 5
            NSLayoutConstraint.Create(lightGreenView, NSLayoutAttribute.Height, NSLayoutRelation.Equal, lightGreenView, NSLayoutAttribute.Width, (nfloat) 0.20, 0),
            //Cannot be larger than parent's width or height
            lightGreenView.WidthAnchor.ConstraintLessThanOrEqualTo(blueView.WidthAnchor),
            lightGreenView.HeightAnchor.ConstraintLessThanOrEqualTo(blueView.HeightAnchor),
            //Center in parent
            lightGreenView.CenterYAnchor.ConstraintEqualTo(blueView.CenterYAnchor),
            lightGreenView.CenterXAnchor.ConstraintEqualTo(blueView.CenterXAnchor)
        };
        //Must-fulfill
        foreach (var c in lightGreenConstraints) 
        {
            c.Priority = 1000;
        }
        NSLayoutConstraint.ActivateConstraints (lightGreenConstraints);

        //Low priority constraint to attempt to fill parent as much as possible (but lower priority than previous)
        var lightGreenLowPriorityConstraints = new []
         {
            lightGreenView.WidthAnchor.ConstraintEqualTo(blueView.WidthAnchor),
            lightGreenView.HeightAnchor.ConstraintEqualTo(blueView.HeightAnchor)
        };
        //Lower priority
        foreach (var c in lightGreenLowPriorityConstraints) 
        {
            c.Priority = 750;
        }

        NSLayoutConstraint.ActivateConstraints (lightGreenLowPriorityConstraints);

        //Aspect-fit on the green view now
        greenView.TranslatesAutoresizingMaskIntoConstraints = false;
        var greenConstraints = new []
        {
            //Aspect ratio of 5:1
            NSLayoutConstraint.Create(greenView, NSLayoutAttribute.Height, NSLayoutRelation.Equal, greenView, NSLayoutAttribute.Width, (nfloat) 5.0, 0),
            //Cannot be larger than parent's width or height
            greenView.WidthAnchor.ConstraintLessThanOrEqualTo(pinkView.WidthAnchor),
            greenView.HeightAnchor.ConstraintLessThanOrEqualTo(pinkView.HeightAnchor),
            //Center in parent
            greenView.CenterXAnchor.ConstraintEqualTo(pinkView.CenterXAnchor),
            greenView.CenterYAnchor.ConstraintEqualTo(pinkView.CenterYAnchor)
        };
        //Must fulfill
        foreach (var c in greenConstraints) 
        {
            c.Priority = 1000;
        }
        NSLayoutConstraint.ActivateConstraints (greenConstraints);

        //Low priority constraint to attempt to fill parent as much as possible (but lower priority than previous)
        var greenLowPriorityConstraints = new []
        {
            greenView.WidthAnchor.ConstraintEqualTo(pinkView.WidthAnchor),
            greenView.HeightAnchor.ConstraintEqualTo(pinkView.HeightAnchor)
        };
        //Lower-priority than above
        foreach (var c in greenLowPriorityConstraints) 
        {
            c.Priority = 750;
        }

        NSLayoutConstraint.ActivateConstraints (greenLowPriorityConstraints);

        this.View = view;

        view.LayoutIfNeeded ();
    }
}

1

บางทีนี่อาจเป็นคำตอบที่สั้นที่สุดสำหรับMasonryซึ่งรองรับการเติมและยืดออก

typedef NS_ENUM(NSInteger, ContentMode) {
    ContentMode_aspectFit,
    ContentMode_aspectFill,
    ContentMode_stretch
}

// ....

[containerView addSubview:subview];

[subview mas_makeConstraints:^(MASConstraintMaker *make) {
    if (contentMode == ContentMode_stretch) {
        make.edges.equalTo(containerView);
    }
    else {
        make.center.equalTo(containerView);
        make.edges.equalTo(containerView).priorityHigh();
        make.width.equalTo(content.mas_height).multipliedBy(4.0 / 3); // the aspect ratio
        if (contentMode == ContentMode_aspectFit) {
            make.width.height.lessThanOrEqualTo(containerView);
        }
        else { // contentMode == ContentMode_aspectFill
            make.width.height.greaterThanOrEqualTo(containerView);
        }
    }
}];
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.