programing

UIStackView에서 프로그래밍 방식으로 보기 추가

muds 2023. 4. 16. 15:55
반응형

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에 대한 파라미터도 가져옵니다.)

스택 뷰는 고유한 컨텐츠 크기를 사용하므로 레이아웃 제약 조건을 사용하여 뷰의 치수를 정의합니다.

제약조건을 신속하게 추가하는 간단한 방법이 있습니다(예).

[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에서 테스트되었습니다.

UIStack View 등간격(중앙)

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의 답변에 근거합니다.

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)
])

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 세부사항을 - -- - 흔흔 、 흔흔 ( 흔 - ) 。

배포 유형을 설정해야 합니다.코드에 다음 내용을 추가합니다.

self.stack1.distribution = UIStackViewDistributionFillEqually;

또는, 인터페이스 빌더로 직접 전달을 설정할 수도 있습니다.예를 들어 다음과 같습니다.

여기에 이미지 설명 입력

그것이 도움이 되기를 바란다;) 라피노.

다음 두 줄에 따라 문제가 해결되었습니다.

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

스택 뷰 내에서 뷰를 숨기려고 할 때 허용되는 응답의 경우 제약조건이 올바르게 작동하지 않습니다.

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)>"
)

그 이유는, 이 파일을 숨김으로써viewstackView높이를 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
    }

}
    //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의 답변보다 개선되었습니다.

Swift 5 버전의 Oleg Popov 답변은 사용자 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

내 경우, 내가 예상한 것은 내가 이 줄을 놓치고 있었다는 것이다.

stackView.translatesAutoresizingMaskIntoConstraints = false;

그 후 정렬된 서브뷰에 제약을 가할 필요가 전혀 없습니다.스택뷰가 그 처리를 하고 있습니다.

UIView를 추가할 때는 할 수 .UIView은 '어디서'에 수 있는 부분이에요.UIStackView

extension UIStackView {
    func addArrangedSubviews(_ subviews: [UIView]) {
        subviews.forEach{ self.addArrangedSubview($0) }
    }
}

특정 위치에 UIView를 추가하려면 다음을 사용하십시오.

yourStackView.insertArrangedSubview(yourView, at: index)

나는 방금 아주 비슷한 문제를 발견했다.스택 뷰의 치수는 앞에서 설명한 바와 같이 정렬된 서브뷰의 고유한 콘텐츠크기에 따라 달라집니다.다음은 Swift 2.x의 솔루션과 다음 뷰 구조입니다.

표시 - UIView

Custom View - Custom View :UIView

stackView - USTackView

정렬된 서브뷰 - 커스텀 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

하는 것이 , 을 처리하는 할 수 ..intrinsicContentSizeUIView더 심플한 방법으로 수업할 수 있습니다. 솔루션에서는, 「intrinsicWidth」및 「intrinsicHeight」뷰를 서포트하기 위해서, Interface Builder도 약간 개선됩니다.귀하는 UIView를 확장하고 이러한 속성을 IB의 모든 UIView에서 사용할 수 있도록 할 수 있지만, 클리너는 하위 클래스로 이동합니다.

// 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

, IntrentialView와 IntrentialView를 할당할 수 .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];
}

UIStackView를 통해 열광할 수 있게 되었습니다.

또는 신속한 + 인코딩, 디코딩, 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)
    }
}

높이 제한을 설정하는 것은 권장되지 않습니다.만약 할 수 있다면, 절대, 절대, 절대 높이를 설정하지 마세요!UIStackView 내 뷰의 모든 구속조건을 체크하고 하단, 상단, 선행 및 후행의 구속조건이 있는지 확인해야 합니다.누군가 나에게 말했다: 그것은 벽을 밀고 있는 사람 같다.사면을 밀지 않으면 한쪽 벽이 무너질 거예요.

func configureHorizontalView(){
    containerView.addSubview(horizontalStackView)
    _ = horizontalStackView.anchor(top: secondCurrencyTextField.bottomAnchor, 
                                   left: containerView.leftAnchor, 
                                   bottom: nil, 
                                   right: containerView.rightAnchor, 
                                   topConstant: 40, 
                                   leftConstant: 30, 
                                   bottomConstant: 0, 
                                   rightConstant: 30, 
                                   widthConstant: 0, 
                                   heightConstant: 65)
}

func configureFirstDropDownlabel(){
    //add a view to stackView with addArrangedSubview() 
    horizontalStackView.addArrangedSubview(firstDropDownlabel)
    _ = firstDropDownlabel.anchor(top: horizontalStackView.bottomAnchor, 
                                  left: horizontalStackView.leftAnchor, 
                                  bottom: nil, right: nil, 
                                  topConstant: 40, 
                                  leftConstant: 30, 
                                  bottomConstant: 0, 
                                  rightConstant: 0, 
                                  widthConstant: 0, 
                                  heightConstant: 0)
    firstDropDownlabel.widthAnchor.constraint(equalToConstant: 130).isActive = true
    firstDropDownlabel.heightAnchor.constraint(equalToConstant: 65).isActive = true
}

아래 코드 시도:

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];

언급URL : https://stackoverflow.com/questions/30728062/add-views-in-uistackview-programmatically

반응형