Программно добавлять представления в UIStackView

Я пытаюсь программно добавить представления в UIStackView. На данный момент мой код:

UIView *view1 = [[UIView alloc]init];
view1.backgroundColor = [UIColor blackColor];
[view1 setFrame:CGRectMake(0, 0, 100, 100)];

UIView *view2 =  [[UIView alloc]init];
view2.backgroundColor = [UIColor greenColor];
[view2 setFrame:CGRectMake(0, 100, 100, 100)];

[self.stack1 addArrangedSubview:view1];
[self.stack1 addArrangedSubview:view2];

Когда я развертываю приложение, есть только 1 представление, и оно черного цвета. (View1 также получает параметры для view2)


person Altimir Antonov    schedule 09.06.2015    source источник
comment
Вы в здравом уме проверили розетку? Вы регистрировали подпредставления во время выполнения?   -  person Wain    schedule 09.06.2015
comment
Используйте addArrangedSubview:, а не addSubview:   -  person pkamb    schedule 01.12.2017


Ответы (14)


Представления стека используют внутренний размер содержимого, поэтому используйте ограничения макета для определения размеров представлений.

Есть простой способ быстро добавить ограничения (пример):

[view1.heightAnchor constraintEqualToConstant:100].active = true;

Полный код:

- (void) setup {

    //View 1
    UIView *view1 = [[UIView alloc] init];
    view1.backgroundColor = [UIColor blueColor];
    [view1.heightAnchor constraintEqualToConstant:100].active = true;
    [view1.widthAnchor constraintEqualToConstant:120].active = true;


    //View 2
    UIView *view2 = [[UIView alloc] init];
    view2.backgroundColor = [UIColor greenColor];
    [view2.heightAnchor constraintEqualToConstant:100].active = true;
    [view2.widthAnchor constraintEqualToConstant:70].active = true;

    //View 3
    UIView *view3 = [[UIView alloc] init];
    view3.backgroundColor = [UIColor magentaColor];
    [view3.heightAnchor constraintEqualToConstant:100].active = true;
    [view3.widthAnchor constraintEqualToConstant:180].active = true;

    //Stack View
    UIStackView *stackView = [[UIStackView alloc] init];

    stackView.axis = UILayoutConstraintAxisVertical;
    stackView.distribution = UIStackViewDistributionEqualSpacing;
    stackView.alignment = UIStackViewAlignmentCenter;
    stackView.spacing = 30;


    [stackView addArrangedSubview:view1];
    [stackView addArrangedSubview:view2];
    [stackView addArrangedSubview:view3];

    stackView.translatesAutoresizingMaskIntoConstraints = false;
    [self.view addSubview:stackView];


    //Layout for Stack View
    [stackView.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor].active = true;
    [stackView.centerYAnchor constraintEqualToAnchor:self.view.centerYAnchor].active = true;
}

Примечание. Это было протестировано на iOS 9.

UIStackView Equal Spacing (  по центру)

person user1046037    schedule 23.07.2015
comment
Смысл использования представлений стека в том, что они скрывают детали управления ограничениями от разработчика. Как вы отметили, это зависит от вложенных представлений, имеющих внутренний размер содержимого, которого по умолчанию UIViews нет. Если бы исходный плакат использовал UILabel экземпляра вместо UIView, его код работал бы так, как он ожидал. Я добавил пример, демонстрирующий это ниже. - person Greg Brown; 30.09.2015
comment
когда я делаю это [view1.heightAnchor constraintEqualToConstant: 100] .active = true; Я получаю ошибку на ios 8. Он работает только на ios 9. Я знаю, что uistackview предназначен для ios 9+, но как я могу установить ограничение heightAncor для ios 8 - person nuridin selimko; 27.10.2015
comment
Мой StackView добавлен с помощью раскадровки. Во время выполнения я добавляю несколько UIView (содержащих другие подпредставления) в stackView. После загрузки данных все представления внутри stackView имеют одинаковую высоту, их размер не изменяется в соответствии с содержимым. @ user1046037 - person Mansuu....; 07.09.2017
comment
Установлены ли у вас ограничения для этих отдельных представлений, чтобы их размер зависел от содержимого? - person user1046037; 07.09.2017
comment
Это лучший и оптимальный способ управления видами с одинаковой шириной или высотой. - person Kampai; 18.09.2017
comment
Версия Swift 5: stackoverflow.com/a/58827722/2273338 - person Abdurrahman Mubeen Ali; 13.11.2019

Swift 5.0

//Image View
let imageView = UIImageView()
imageView.backgroundColor = UIColor.blue
imageView.heightAnchor.constraint(equalToConstant: 120.0).isActive = true
imageView.widthAnchor.constraint(equalToConstant: 120.0).isActive = true
imageView.image = UIImage(named: "buttonFollowCheckGreen")

//Text Label
let textLabel = UILabel()
textLabel.backgroundColor = UIColor.yellow
textLabel.widthAnchor.constraint(equalToConstant: self.view.frame.width).isActive = true
textLabel.heightAnchor.constraint(equalToConstant: 20.0).isActive = true
textLabel.text  = "Hi World"
textLabel.textAlignment = .center

//Stack View
let stackView   = UIStackView()
stackView.axis  = NSLayoutConstraint.Axis.vertical
stackView.distribution  = UIStackView.Distribution.equalSpacing
stackView.alignment = UIStackView.Alignment.center
stackView.spacing   = 16.0

stackView.addArrangedSubview(imageView)
stackView.addArrangedSubview(textLabel)
stackView.translatesAutoresizingMaskIntoConstraints = false

self.view.addSubview(stackView)

//Constraints
stackView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
stackView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true

На основе ответа @ user1046037.

person Oleg Popov    schedule 20.09.2015
comment
Начиная с iOS 8, можно активировать ограничения в пакетном режиме с помощью activate(_:), и обычно более эффективно сделать это таким образом developer.apple.com/documentation/uikit/nslayoutconstraint/ - person Jonathan Cabrera; 17.12.2018
comment
Версия Swift 5: stackoverflow.com/a/58827722/2273338 - person Abdurrahman Mubeen Ali; 13.11.2019

В Swift 4.2

let redView = UIView()
redView.backgroundColor = .red

let blueView = UIView()
blueView.backgroundColor = .blue

let stackView = UIStackView(arrangedSubviews: [redView, blueView])
stackView.axis = .vertical
stackView.distribution = .fillEqually

view.addSubview(stackView)

// stackView.frame = CGRect(x: 0, y: 0, width: 200, height: 200)

// autolayout constraint
stackView.translatesAutoresizingMaskIntoConstraints = false

NSLayoutConstraint.activate([
    stackView.topAnchor.constraint(equalTo: view.topAnchor),
    stackView.leftAnchor.constraint(equalTo: view.leftAnchor),
    stackView.rightAnchor.constraint(equalTo: view.rightAnchor),
    stackView.heightAnchor.constraint(equalToConstant: 200)
])
person Ashim Dahal    schedule 18.12.2018

UIStackView использует внутренние ограничения для позиционирования упорядоченных подвидов. Какие именно ограничения создаются, зависит от того, как настроено само представление стека. По умолчанию представление стека создает ограничения, которые размещают его упорядоченные подвиды в горизонтальной линии, закрепляя ведущие и замыкающие представления на своих собственных передних и задних краях. Таким образом, ваш код создаст макет, который выглядит следующим образом:

|[view1][view2]|

Пространство, выделяемое для каждого подпредставления, определяется рядом факторов, включая внутренний размер содержимого подпредставления, его сопротивление сжатию и приоритеты прилегания к содержимому. По умолчанию UIView экземпляры не определяют внутренний размер содержимого. Это то, что обычно предоставляется подклассом, например UILabel или UIButton.

Поскольку сопротивление сжатию содержимого и приоритеты объятия содержимого у двух новых UIView экземпляров будут одинаковыми, и ни одно представление не обеспечивает внутреннего размера содержимого, механизм компоновки должен наилучшим образом угадать, какой размер должен быть выделен для каждого представления. В вашем случае он назначает первому виду 100% доступного пространства и ничего второму виду.

Если вы измените свой код, чтобы вместо этого использовать экземпляры UILabel, вы получите лучшие результаты:

UILabel *label1 = [UILabel new];
label1.text = @"Label 1";
label1.backgroundColor = [UIColor blueColor];

UILabel *label2 = [UILabel new];
label2.text = @"Label 2";
label2.backgroundColor = [UIColor greenColor];

[self.stack1 addArrangedSubview:label1];
[self.stack1 addArrangedSubview:label2];

Обратите внимание, что нет необходимости явно создавать какие-либо ограничения самостоятельно. Это главное преимущество использования UIStackView - оно скрывает (часто уродливые) детали управления ограничениями от разработчика.

person Greg Brown    schedule 30.09.2015
comment
У меня та же проблема, что это работает для ярлыков, но не для текстовых полей (или представлений, если на то пошло). Также во всех обучающих материалах используются ярлыки, изображения или кнопки. Означает ли это, что мы не можем использовать этот метод ни для чего другого, кроме этих элементов пользовательского интерфейса? - person physicalattraction; 27.01.2016
comment
@physicalattraction Представления, которые вы добавляете в представление стека, должны иметь внутренний размер содержимого. Насколько я помню, внутренний размер текстового поля зависит от содержимого поля (что нечетно). Экземпляры самого UIView не имеют собственного размера. Возможно, вам придется применить дополнительные ограничения к этим представлениям, чтобы представление стека знало, насколько они велики. - person Greg Brown; 27.01.2016
comment
Имеет смысл, поэтому я пробую. Теперь я создал представление в xib с текстовым полем, для которого я задаю явное ограничение по высоте в 30 пикселей. Кроме того, я налагаю следующие два ограничения: MyTextField.top = top+20 и bottom = MyTextField.bottom+20. Я ожидал, что это даст моему представлению внутреннюю высоту 70, но вместо этого он жалуется на противоречивые ограничения. Вы знаете, что здесь происходит? Именно это представление я хочу поместить в свой UIStackView. - person physicalattraction; 27.01.2016
comment
Думаю, я знаю, в чем проблема. Представление стека автоматически прикрепляет свое окончательно упорядоченное подвид к его нижнему краю. Таким образом, представление стека пытается сделать ваш контейнер таким же размером, как и он сам. Однако вы сказали этому представлению, что оно должно быть 70 пикселей в высоту, что создает конфликт. Попробуйте создать дополнительное пустое представление сразу после представления контейнера и назначьте ему приоритет вертикального размещения содержимого, равный 0. Задайте для представления контейнера приоритет вертикального размещения содержимого, равный 1000. Это приведет к тому, что пустое представление будет растягиваться, чтобы заполнить пустое пространство в стеке. Посмотреть. - person Greg Brown; 27.01.2016
comment
Я предполагаю, что вы, кстати, используете вертикальное представление стека. Вы также можете прочитать эту статью о представлениях стека, которую я написал: dzone .com / article / - person Greg Brown; 27.01.2016
comment
Спасибо, я проверю эту статью позже на этой неделе. Жалобы на конфликтующие ограничения были только в UIView, даже не помещая их в StackView. Я заметил, что могу хотя бы успокоить Xcode, понизив приоритет двух из трех ограничений, но я все еще пытаюсь исправить это. - person physicalattraction; 28.01.2016

Вам необходимо указать тип распространения. В вашем коде добавьте:

self.stack1.distribution = UIStackViewDistributionFillEqually;

Или вы можете установить дистрибутив прямо в построителе интерфейса. Например:

введите описание изображения здесь

Надеюсь, что это поможет;) Лапиноу.

person Lapinou    schedule 09.06.2015

Следующие две строки исправили мою проблему

view.heightAnchor.constraintEqualToConstant(50).active = true;
view.widthAnchor.constraintEqualToConstant(350).active = true;

Быстрая версия -

var DynamicView=UIView(frame: CGRectMake(100, 200, 100, 100))
DynamicView.backgroundColor=UIColor.greenColor()
DynamicView.layer.cornerRadius=25
DynamicView.layer.borderWidth=2
self.view.addSubview(DynamicView)
DynamicView.heightAnchor.constraintEqualToConstant(50).active = true;
DynamicView.widthAnchor.constraintEqualToConstant(350).active = true;

var DynamicView2=UIView(frame: CGRectMake(100, 310, 100, 100))
DynamicView2.backgroundColor=UIColor.greenColor()
DynamicView2.layer.cornerRadius=25
DynamicView2.layer.borderWidth=2
self.view.addSubview(DynamicView2)
DynamicView2.heightAnchor.constraintEqualToConstant(50).active = true;
DynamicView2.widthAnchor.constraintEqualToConstant(350).active = true;

var DynamicView3:UIView=UIView(frame: CGRectMake(10, 420, 355, 100))
DynamicView3.backgroundColor=UIColor.greenColor()
DynamicView3.layer.cornerRadius=25
DynamicView3.layer.borderWidth=2
self.view.addSubview(DynamicView3)

let yourLabel:UILabel = UILabel(frame: CGRectMake(110, 10, 200, 20))
yourLabel.textColor = UIColor.whiteColor()
//yourLabel.backgroundColor = UIColor.blackColor()
yourLabel.text = "mylabel text"
DynamicView3.addSubview(yourLabel)
DynamicView3.heightAnchor.constraintEqualToConstant(50).active = true;
DynamicView3.widthAnchor.constraintEqualToConstant(350).active = true;

let stackView   = UIStackView()
stackView.axis  = UILayoutConstraintAxis.Vertical
stackView.distribution  = UIStackViewDistribution.EqualSpacing
stackView.alignment = UIStackViewAlignment.Center
stackView.spacing   = 30

stackView.addArrangedSubview(DynamicView)
stackView.addArrangedSubview(DynamicView2)
stackView.addArrangedSubview(DynamicView3)

stackView.translatesAutoresizingMaskIntoConstraints = false;

self.view.addSubview(stackView)

//Constraints
stackView.centerXAnchor.constraintEqualToAnchor(self.view.centerXAnchor).active = true
stackView.centerYAnchor.constraintEqualToAnchor(self.view.centerYAnchor).active = true
person Ekta    schedule 29.11.2015

Для принятого ответа, когда вы пытаетесь скрыть какое-либо представление внутри представления стека, ограничение работает неправильно.

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. 
(
    "<NSLayoutConstraint:0x618000086e50 UIView:0x7fc11c4051c0.height == 120   (active)>",
    "<NSLayoutConstraint:0x610000084fb0 'UISV-hiding' UIView:0x7fc11c4051c0.height == 0   (active)>"
)

Причина в том, что если скрыть view в stackView, высота будет установлена ​​равной 0 для его анимации.

Решение измените ограничение priority, как показано ниже.

import UIKit

class ViewController: UIViewController {

    let stackView = UIStackView()
    let a = UIView()
    let b = UIView()

    override func viewDidLoad() {
        super.viewDidLoad()

        a.backgroundColor = UIColor.red
        a.widthAnchor.constraint(equalToConstant: 200).isActive = true
        let aHeight = a.heightAnchor.constraint(equalToConstant: 120)
        aHeight.isActive = true
        aHeight.priority = 999

        let bHeight = b.heightAnchor.constraint(equalToConstant: 120)
        bHeight.isActive = true
        bHeight.priority = 999
        b.backgroundColor = UIColor.green
        b.widthAnchor.constraint(equalToConstant: 200).isActive = true

        view.addSubview(stackView)
        stackView.backgroundColor = UIColor.blue
        stackView.addArrangedSubview(a)
        stackView.addArrangedSubview(b)
        stackView.axis = .vertical
        stackView.distribution = .equalSpacing
        stackView.translatesAutoresizingMaskIntoConstraints = false
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    // Just add a button in xib file or storyboard and add connect this action.
    @IBAction func test(_ sender: Any) {
        a.isHidden = !a.isHidden
    }

}
person William Hu    schedule 26.07.2017

    //Image View
    let imageView               = UIImageView()
    imageView.backgroundColor   = UIColor.blueColor()
    imageView.heightAnchor.constraintEqualToConstant(120.0).active = true
    imageView.widthAnchor.constraintEqualToConstant(120.0).active = true
    imageView.image = UIImage(named: "buttonFollowCheckGreen")

    //Text Label
    let textLabel               = UILabel()
    textLabel.backgroundColor   = UIColor.greenColor()
    textLabel.widthAnchor.constraintEqualToConstant(self.view.frame.width).active = true
    textLabel.heightAnchor.constraintEqualToConstant(20.0).active = true
    textLabel.text  = "Hi World"
    textLabel.textAlignment = .Center


    //Third View
    let thirdView               = UIImageView()
    thirdView.backgroundColor   = UIColor.magentaColor()
    thirdView.heightAnchor.constraintEqualToConstant(120.0).active = true
    thirdView.widthAnchor.constraintEqualToConstant(120.0).active = true
    thirdView.image = UIImage(named: "buttonFollowMagenta")


    //Stack View
    let stackView   = UIStackView()
    stackView.axis  = UILayoutConstraintAxis.Vertical
    stackView.distribution  = UIStackViewDistribution.EqualSpacing
    stackView.alignment = UIStackViewAlignment.Center
    stackView.spacing   = 16.0

    stackView.addArrangedSubview(imageView)
    stackView.addArrangedSubview(textLabel)
    stackView.addArrangedSubview(thirdView)
    stackView.translatesAutoresizingMaskIntoConstraints = false;

    self.view.addSubview(stackView)

    //Constraints
    stackView.centerXAnchor.constraintEqualToAnchor(self.view.centerXAnchor).active = true
    stackView.centerYAnchor.constraintEqualToAnchor(self.view.centerYAnchor).active = true

Улучшен ответ @Oleg Popov

person Arunabh Das    schedule 22.09.2015

В моем случае, я ожидал, что мне не хватало этой строки:

stackView.translatesAutoresizingMaskIntoConstraints = false;

После этого не нужно вообще устанавливать ограничения для моих упорядоченных подпредставлений, об этом позаботится stackview.

person PakitoV    schedule 14.02.2019

Swift 5 версии ответа Олега Попова, который основан на ответ пользователя1046037

//Image View
let imageView = UIImageView()
imageView.backgroundColor = UIColor.blue
imageView.heightAnchor.constraint(equalToConstant: 120.0).isActive = true
imageView.widthAnchor.constraint(equalToConstant: 120.0).isActive = true
imageView.image = UIImage(named: "buttonFollowCheckGreen")

//Text Label
let textLabel = UILabel()
textLabel.backgroundColor = UIColor.yellow
textLabel.widthAnchor.constraint(equalToConstant: self.view.frame.width).isActive = true
textLabel.heightAnchor.constraint(equalToConstant: 20.0).isActive = true
textLabel.text  = "Hi World"
textLabel.textAlignment = .center

//Stack View
let stackView   = UIStackView()
stackView.axis  = NSLayoutConstraint.Axis.vertical
stackView.distribution  = UIStackView.Distribution.equalSpacing
stackView.alignment = UIStackView.Alignment.center
stackView.spacing   = 16.0

stackView.addArrangedSubview(imageView)
stackView.addArrangedSubview(textLabel)
stackView.translatesAutoresizingMaskIntoConstraints = false

self.view.addSubview(stackView)

//Constraints
stackView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
stackView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
person Abdurrahman Mubeen Ali    schedule 12.11.2019

Я столкнулся с очень похожей проблемой. Как уже упоминалось ранее, размеры представления стека зависят от внутреннего размера содержимого упорядоченных подпредставлений. Вот мое решение в Swift 2.x и следующая структура представления:

просмотр - UIView

customView - CustomView: UIView

stackView - UISTackView

упорядоченные подпредставления - настраиваемые подклассы UIView

    //: [Previous](@previous)

import Foundation
import UIKit
import XCPlayground

/**Container for stack view*/
class CustomView:UIView {

    override init(frame: CGRect) {
        super.init(frame: frame)
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }


    init(){
        super.init(frame: CGRectZero)

    }

}

/**Custom Subclass*/
class CustomDrawing:UIView{
    override init(frame: CGRect) {
        super.init(frame: frame)
        setup()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setup()

    }

    func setup(){
       // self.backgroundColor = UIColor.clearColor()
        print("setup \(frame)")
    }

    override func drawRect(rect: CGRect) {
        let ctx = UIGraphicsGetCurrentContext()
        CGContextMoveToPoint(ctx, 0, 0)
        CGContextAddLineToPoint(ctx, CGRectGetWidth(bounds), CGRectGetHeight(bounds))
        CGContextStrokePath(ctx)

        print("DrawRect")

    }
}



//: [Next](@next)
let stackView = UIStackView()
stackView.distribution = .FillProportionally
stackView.alignment = .Center
stackView.axis = .Horizontal
stackView.spacing = 10


//container view
let view = UIView(frame: CGRectMake(0,0,320,640))
view.backgroundColor = UIColor.darkGrayColor()
//now custom view

let customView = CustomView()

view.addSubview(customView)

customView.translatesAutoresizingMaskIntoConstraints = false
customView.widthAnchor.constraintEqualToConstant(220).active = true
customView.heightAnchor.constraintEqualToConstant(60).active = true
customView.centerXAnchor.constraintEqualToAnchor(view.centerXAnchor).active = true
customView.centerYAnchor.constraintEqualToAnchor(view.centerYAnchor).active = true
customView.backgroundColor = UIColor.lightGrayColor()

//add a stack view
customView.addSubview(stackView)
stackView.centerXAnchor.constraintEqualToAnchor(customView.centerXAnchor).active = true
stackView.centerYAnchor.constraintEqualToAnchor(customView.centerYAnchor).active = true
stackView.translatesAutoresizingMaskIntoConstraints = false


let c1 = CustomDrawing()
c1.translatesAutoresizingMaskIntoConstraints = false
c1.backgroundColor = UIColor.redColor()
c1.widthAnchor.constraintEqualToConstant(30).active = true
c1.heightAnchor.constraintEqualToConstant(30).active = true

let c2 = CustomDrawing()
c2.translatesAutoresizingMaskIntoConstraints = false
c2.backgroundColor = UIColor.blueColor()
c2.widthAnchor.constraintEqualToConstant(30).active = true
c2.heightAnchor.constraintEqualToConstant(30).active = true


stackView.addArrangedSubview(c1)
stackView.addArrangedSubview(c2)


XCPlaygroundPage.currentPage.liveView = view
person Janusz Chudzynski    schedule 25.03.2016

Вместо кодирования всех ограничений вы можете использовать подкласс, который более простым способом обрабатывает .intrinsicContentSize из UIView. Это решение также немного улучшает Interface Builder в части поддержки представлений intrinsicWidth и intrinsicHeight. Хотя вы можете расширить UIView и сделать эти свойства доступными для всех UIView в IB, его очиститель будет подклассом.

// IntrinsicView.h
@import UIKit

IB_DESIGNABLE
@interface IntrinsicView : UIView
-(instancetype)initWithFrame:(CGRect)rect;
@property IBInspectable CGSize intrinsic;
@end
// IntrinsicView.m
#import "IntrinsicView.h"

@implementation IntrinsicView {
    CGSize _intrinsic;
}
- (instancetype)initWithFrame:(CGRect)frame {
    _intrinsic = frame.size;
    if ( !(self = [super initWithFrame:frame]) ) return nil;
    // your stuff here..
    return self;
}
-(CGSize)intrinsicContentSize {
    return _intrinsic;
}
-(void)prepareForInterfaceBuilder {
    self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, _intrinsic.width,_intrinsic.height);
}
@end

Это означает, что вы можете просто выделить эти IntrinsicView, и self.frame.size будет приниматься как intrinsicContentSize. Таким образом, это не нарушает нормальный макет, и вам не нужно устанавливать отношения ограничений, которые даже не применяются полностью с UIStackViews

#import "IntrinsicView.h"

- (void)viewDidLoad {
    [super viewDidLoad];
    
    UIStackView *column = [[UIStackView alloc] initWithFrame:self.view.frame];
    column.spacing = 2;
    column.alignment = UIStackViewAlignmentFill;
    column.axis = UILayoutConstraintAxisVertical; //Up-Down
    column.distribution = UIStackViewDistributionFillEqually;
    
    for (int row=0; row<5; row++) {
        //..frame:(CGRect) defines here proportions and
        //relation to axis of StackView
        IntrinsicView *intrinsicView = [[IntrinsicView alloc] initWithFrame:CGRectMake(0, 0, 30.0, 30.0)];
        
        [column addArrangedSubview:intrinsicView];
    }
    [self.view addSubview:column];
}

теперь вы можете сойти с ума с помощью  введите описание изображения здесь

или в swift + кодирование, декодирование, поддержка IB, поддержка Objective-C

@IBDesignable @objc class IntrinsicView : UIView {
    @IBInspectable var intrinsic : CGSize
    @objc override init(frame: CGRect) {
        intrinsic = frame.size
        super.init(frame: frame)
    }
    required init?(coder: NSCoder) {
        intrinsic = coder.decodeCGSize(forKey: "intrinsic")
        super.init(coder: coder)
    }
    override func encode(with coder: NSCoder) {
        coder.encode(intrinsic, forKey: "intrinsic")
        super.encode(with: coder)
    }
    override var intrinsicContentSize: CGSize {
        return intrinsic
    }
    override func prepareForInterfaceBuilder() {
        frame = CGRect(x: self.frame.origin.x, y: self.frame.origin.y, width: intrinsic.width, height: intrinsic.height)
    }
}
person Ol Sen    schedule 31.07.2020

На самом деле не рекомендуется устанавливать ограничение по высоте ... Если вы можете, никогда, никогда, никогда не устанавливайте высоту! Вам нужно проверить все ограничения представлений внутри вашего UIStackView и убедиться, что есть ограничения для нижнего, верхнего, ведущего и замыкающего. Кто-то сказал мне: это как если парень толкает стены. Если он не толкнет с 4 сторон, одна стена упадет на него.

person Barbara K    schedule 18.02.2021

Попробуйте код ниже,

UIView *view1 = [[UIView alloc]init];
view1.backgroundColor = [UIColor blackColor];
[view1 setFrame:CGRectMake(0, 0, 50, 50)];

UIView *view2 =  [[UIView alloc]init];
view2.backgroundColor = [UIColor greenColor];
[view2 setFrame:CGRectMake(0, 100, 100, 100)];

NSArray *subView = [NSArray arrayWithObjects:view1,view2, nil];

[self.stack1 initWithArrangedSubviews:subView];

Надеюсь, что это работает. Пожалуйста, дайте мне знать, если вам нужны дополнительные разъяснения.

person Nilesh Patel    schedule 10.06.2015