developer tip

프로그래밍 방식으로 레이아웃 제약 만들기

copycodes 2020. 9. 18. 08:19
반응형

프로그래밍 방식으로 레이아웃 제약 만들기


많은 사람들이 이미 이것에 대해 많은 질문을했지만 대답을하더라도 제대로 작동하지 않는다는 것을 알고 있습니다.

스토리 보드의 제약을 다룰 때는 쉽지만 코드에서는 힘들다. 예를 들어 화면 방향에 따라 화면의 높이가 오른쪽에 유지되는 뷰를 만들려고합니다. 이것은 내 코드입니다.

UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 748)];
myView.backgroundColor = [UIColor redColor];
[self.view addSubview:myView];
[self.view addConstraints:[NSLayoutConstraint
    constraintsWithVisualFormat:@"V:|-[myView(>=748)]-|"
    options:0 metrics:nil
    views:NSDictionaryOfVariableBindings(myView)]];

일부 제약 조건을 충족하지 않습니다. 나는 무엇이 잘못되었는지 모르겠다. 또한 왜 같은 self.myView지역 변수 대신 같은 속성을 사용할 수 myView없습니까?


코드에서 자동 레이아웃을 사용할 때 프레임 설정은 아무 작업도 수행하지 않습니다. 따라서 위의 뷰에서 너비를 200으로 지정했다는 사실은 제약 조건을 설정할 때 아무런 의미가 없습니다. 뷰의 제약 조건이 명확하게 설정 되려면 주어진 상태에 대한 x 위치, y 위치, 너비 및 높이의 네 가지가 필요합니다.

현재 위의 코드에는 두 개만 있습니다 (슈퍼 뷰를 기준으로 한 높이와 수퍼 뷰를 기준으로 한 y 위치). 이 외에도 뷰의 수퍼 뷰의 제약이 설정되는 방식에 따라 충돌 할 수있는 두 가지 필수 제약이 있습니다. 경우 수퍼가 지정 그것의 높이가 748보다 약간 작은 값 것이 필요한 제약 조건을 가지고 있었다, 당신은 "시켰음 제약"예외를 얻을 것이다.

제약 조건을 설정하기 전에 뷰의 너비를 설정했다는 사실은 의미가 없습니다. 이전 프레임도 고려하지 않고 해당 뷰에 대해 지정한 모든 제약 조건을 기반으로 새 프레임을 계산합니다. 코드에서 자동 레이아웃을 처리 할 때 일반적으로 initWithFrame:CGRectZero또는 단순히 사용하여 새보기를 만듭니다 init.

질문에서 구두로 설명한 레이아웃에 필요한 제약 집합을 만들려면 완전히 지정된 레이아웃을 제공하기 위해 너비와 x 위치를 제한하는 몇 가지 수평 제약 조건을 추가해야합니다.

[self.view addConstraints:[NSLayoutConstraint
    constraintsWithVisualFormat:@"V:|-[myView(>=748)]-|"
    options:NSLayoutFormatDirectionLeadingToTrailing
    metrics:nil
    views:NSDictionaryOfVariableBindings(myView)]];

[self.view addConstraints:[NSLayoutConstraint
    constraintsWithVisualFormat:@"H:[myView(==200)]-|"
    options:NSLayoutFormatDirectionLeadingToTrailing
    metrics:nil
    views:NSDictionaryOfVariableBindings(myView)]];

이 레이아웃을 구두로 설명하면 수직 제약 조건부터 다음과 같이 읽습니다.

myView는 수퍼 뷰의 높이를 표준 공간과 동일한 상단 및 하단 패딩으로 채 웁니다. myView의 superview는 최소 높이가 748pts입니다. myView의 너비는 200pts이며 superview에 대한 표준 공간과 동일한 오른쪽 패딩이 있습니다.

슈퍼 뷰의 높이를 제한하지 않고 전체 슈퍼 뷰의 높이를 단순히 뷰가 채우도록 (>=748)하려면 시각적 형식 텍스트에서 매개 변수를 생략하면 됩니다. (>=748)높이를 지정하는 데 매개 변수가 필요 하다고 생각하는 경우-이 경우 에는 필요하지 않습니다. 막대 ( |) 또는 공백 ( |-, -|) 구문이 있는 막대를 사용하여 뷰를 수퍼 뷰의 가장자리에 고정하면 뷰에 y를 제공합니다. -position (단일 모서리에 뷰 고정) 및 높이가있는 y 위치 (양쪽 모서리에 뷰 고정)를 사용하여 뷰에 대한 제약 설정을 충족합니다.

두 번째 질문과 관련하여 :

사용 NSDictionaryOfVariableBindings(self.myView)(myView에 대한 속성 설정이있는 경우)을 self.myViewVFL 텍스트 에 사용하기 위해 VFL에 공급 하면 자동 레이아웃이 VFL 텍스트를 구문 분석하려고 할 때 예외가 발생할 수 있습니다. 그것은 사전 키의 점 표기법과 사용하려는 시스템과 관련이 있습니다 valueForKeyPath:. 유사한 질문과 답변을 보려면 여기를 참조하십시오 .


안녕하세요 저는 제약 조건과 "방법"에 대해이 페이지를 많이 사용하고 있습니다. 내가 필요하다는 것을 깨닫는 데는 영원히 걸렸습니다.

myView.translatesAutoresizingMaskIntoConstraints = NO;

이 예제가 작동하도록합니다. Userxxx, Rob M. 그리고 특히 여기에 설명과 코드를 제공해 주신 larsacus에게 감사드립니다. 매우 귀중했습니다.

다음은 위의 예제를 실행하기위한 전체 코드입니다.

UIView *myView = [[UIView alloc] init];
myView.backgroundColor = [UIColor redColor];
myView.translatesAutoresizingMaskIntoConstraints = NO;  //This part hung me up 
[self.view addSubview:myView];
//needed to make smaller for iPhone 4 dev here, so >=200 instead of 748
[self.view addConstraints:[NSLayoutConstraint
                           constraintsWithVisualFormat:@"V:|-[myView(>=200)]-|"
                           options:NSLayoutFormatDirectionLeadingToTrailing
                           metrics:nil
                           views:NSDictionaryOfVariableBindings(myView)]];

[self.view addConstraints:[NSLayoutConstraint
                           constraintsWithVisualFormat:@"H:[myView(==200)]-|"
                           options:NSLayoutFormatDirectionLeadingToTrailing
                           metrics:nil
                           views:NSDictionaryOfVariableBindings(myView)]];

Swift 버전

Swift 3 업데이트

This example will show two methods to programmatically add the following constraints the same as if doing it in the Interface Builder:

Width and Height

enter image description here

Center in Container

enter image description here

Boilerplate code

override func viewDidLoad() {
    super.viewDidLoad()

    // set up the view
    let myView = UIView()
    myView.backgroundColor = UIColor.blue
    myView.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(myView)

    // Add constraints code here (choose one of the methods below)
    // ...
}

Method 1: Anchor Style

// width and height
myView.widthAnchor.constraint(equalToConstant: 200).isActive = true
myView.heightAnchor.constraint(equalToConstant: 100).isActive = true

// center in container
myView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
myView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true

Method 2: NSLayoutConstraint Style

// width and height
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

// center in container
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

Notes

  • Anchor style is the preferred method over NSLayoutConstraint Style, however it is only available from iOS 9, so if you are supporting iOS 8 then you should still use NSLayoutConstraint Style.
  • See also the Programmatically Creating Constraints documentation.
  • See this answer for a similar example of adding a pinning constraint.

Regarding your second question about properties, you can use self.myView only if you declared it as a property in class. Since myView is a local variable, you can not use it that way. For more details on this, I would recommend you to go through the apple documentation on Declared Properties,


why can't I use a property like self.myView instead of a local variable like myView?

try using:

NSDictionaryOfVariableBindings(_view)

instead of self.view


Please also note that from iOS9 we can define constraints programmatically "more concise, and easier to read" using subclasses of the new helper class NSLayoutAnchor.

An example from the doc:

[self.cancelButton.leadingAnchor constraintEqualToAnchor:self.saveButton.trailingAnchor constant: 8.0].active = true;

참고URL : https://stackoverflow.com/questions/12826878/creating-layout-constraints-programmatically

반응형