IT story

Visual Format Language를 사용하여 슈퍼 뷰에서 뷰 중심 맞추기

hot-time 2020. 6. 3. 08:21
반응형

Visual Format Language를 사용하여 슈퍼 뷰에서 뷰 중심 맞추기


방금 iOS 용 AutoLayout을 배우기 시작했고 Visual Format Language를 살펴 보았습니다.

한 가지를 제외하고는 모두 잘 작동합니다. 수퍼 뷰 내에서 중심을 볼 수는 없습니다.
VFL에서 가능합니까? 직접 제약 조건을 직접 만들어야합니까?


현재 VFL 사용하여 수퍼 뷰에서 뷰를 중앙에 배치하는 것이 불가능한 것처럼 보이지 않습니다 . 그러나 단일 VFL 문자열과 단일 추가 제약 조건 (축당)을 사용하여 수행하는 것은 그리 어렵지 않습니다.

VFL : "|-(>=20)-[view]-(>=20)-|"

[NSLayoutConstraint constraintWithItem:view
                             attribute:NSLayoutAttributeCenterX
                             relatedBy:NSLayoutRelationEqual
                                toItem:view.superview
                             attribute:NSLayoutAttributeCenterX
                            multiplier:1.f constant:0.f];

당신은 단순히 이것을 할 수 있다고 생각할 것입니다 (이 질문을 보았을 때 처음에 생각하고 시도한 것입니다).

[NSLayoutConstraint constraintsWithVisualFormat:@"|-(>=20)-[view(==200)]-(>=20)-|"
                                 options: NSLayoutFormatAlignAllCenterX | NSLayoutFormatAlignAllCenterY
                                 metrics:nil
                                   views:@{@"view" : view}];

위의 변형을 내 의지에 구부리려고 여러 가지 변형을 시도했지만 두 축 ( H:|V:)에 대해 두 개의 별도 VFL 문자열을 명시 적으로 가지고있는 경우에도 슈퍼 뷰에 적용되지 않는 것으로 보입니다 . 그런 다음 옵션 VFL에 적용될 때 정확하게 시도하고 격리하기 시작했습니다 . VFL의 수퍼 뷰 에는 적용 되지 않는 것으로 보이며 VFL 문자열에 언급 된 명시 적 뷰에만 적용됩니다 (일부 경우 실망).

앞으로 애플은 VFL의 슈퍼 뷰 외에 단 하나의 명시적인 뷰만있을 때만 VFL 옵션이 슈퍼 뷰를 고려할 수있는 새로운 옵션을 추가하기를 희망합니다. 또 다른 해결책은 VFL로 전달되는 다른 옵션이 될 수 있습니다 NSLayoutFormatOptionIncludeSuperview.

말할 필요도없이, 나는 VFL에 대해이 질문에 대답하려고 많은 것을 배웠습니다.


예, Visual Format Language를 사용하여 슈퍼 뷰에서 뷰를 중앙에 배치 할 수 있습니다. 수직 및 수평 모두. 데모는 다음과 같습니다.

https://github.com/evgenyneu/center-vfl


제약 조건을 수동으로 만드는 것이 좋습니다.

[superview addConstraint:
 [NSLayoutConstraint constraintWithItem:view
                              attribute:NSLayoutAttributeCenterX
                              relatedBy:NSLayoutRelationEqual
                                 toItem:superview
                              attribute:NSLayoutAttributeCenterX
                             multiplier:1
                               constant:0]];
[superview addConstraint:
 [NSLayoutConstraint constraintWithItem:view
                              attribute:NSLayoutAttributeCenterY
                              relatedBy:NSLayoutRelationEqual
                                 toItem:superview
                              attribute:NSLayoutAttributeCenterY
                             multiplier:1
                               constant:0]];

이제 NSLayoutAnchor사용 하여 AutoLayout을 프로그래밍 방식으로 정의 할 수 있습니다 .

(iOS 9.0 이상에서 사용 가능)

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

iOS와 macOS 모두에서 자동 레이아웃을 쉽게하기 위해 DSL 인 SnapKit을 사용하는 것이 좋습니다 .

view.snp.makeConstraints({ $0.center.equalToSuperview() })

절대적으로 다음과 같이 할 수있었습니다.

[NSLayoutConstraint constraintsWithVisualFormat:@"H:[view]-(<=1)-[subview]"
                                        options:NSLayoutFormatAlignAllCenterY
                                        metrics:nil
                                          views:NSDictionaryOfVariableBindings(view, subview)];

여기 에서 이것을 배웠 습니다. 위의 코드는 분명히 Y에 의해 하위 뷰를 볼 수 있습니다.

스위프트 3 :

        NSLayoutConstraint.constraints(withVisualFormat: "H:[view]-(<=1)-[subview]",
                                       options: .alignAllCenterY,
                                                       metrics: nil,
                                                       views: ["view":self, "subview":_spinnerView])

아래 코드를 추가하고 버튼을 화면 중앙에 두십시오. 물론 가능합니다.

[self.view addConstraints:[NSLayoutConstraint
                           constraintsWithVisualFormat:@"H:|-[button]-|"
                           options:NSLayoutFormatAlignAllCenterY
                           metrics:0
                           views:views]];

[self.view addConstraints:[NSLayoutConstraint
                           constraintsWithVisualFormat:@"V:|-[button]-|"
                           options:NSLayoutFormatAlignAllCenterX
                           metrics:0
                           views:views]];

I know it's not want you want but you can of course calculate the margins and use them to create the visual format string ;)

Anyway, no. Unfortunatly it's not possible to do that 'automatically' with VFL - at least not yet.


Thanks to the answer from @Evgenii, I create a full example in gist:

center the red square vertically with custom height

https://gist.github.com/yallenh/9fc2104b719742ae51384ed95dcaf626

You can center a view vertically by useing either VFL (which is not quite intuitive) or use constraints manually. By the way, I cannot combine both centerY and height together in VFL like:

"H:[subView]-(<=1)-[followIcon(==customHeight)]"

In the current solution VFL constraints are added separately.


What it have to be done is that superview should be declared in the dictionary. Instead of using | you use @{@"super": view.superview};.

And NSLayoutFormatAlignAllCenterX for vertical and NSLayoutFormatAlignAllCenterY for horizontal as options.


You can use extra views.

NSDictionary *formats =
@{
  @"H:|[centerXView]|": @0,
  @"V:|[centerYView]|": @0,
  @"H:[centerYView(0)]-(>=0)-[yourView]": @(NSLayoutFormatAlignAllCenterY),
  @"V:[centerXView(0)]-(>=0)-[yourView]": @(NSLayoutFormatAlignAllCenterX),
};
NSDictionary *views = @{
  @"centerXView": centerXView, 
  @"centerYView": centerYView, 
  @"yourView": yourView,
};
 ^(NSString *format, NSNumber *options, BOOL *stop) {
     [superview addConstraints:
      [NSLayoutConstraint constraintsWithVisualFormat:format
                                              options:options.integerValue
                                              metrics:nil
                                                views:views]];
 }];

If you want it neat, then centerXView.hidden = centerYView.hidden = YES;.

PS: I am not sure I can call the extra views "placeholders", because English is my second language. It will be appreciated if someone can tell me that.


For those who came here for an Interface Builder based solution (Google leads me here), just add const width/height constraints, and select the subview -> control drag to it's superview -> select "center vertically/horizontally in superview".


Just need to say, that u can use this instead of constraints:

child.center = [parent convertPoint:parent.center fromView:parent.superview];

@igor-muzyka answer in Swift 2:

NSLayoutConstraint.constraintsWithVisualFormat("H:[view]-(<=1)-[subview]", 
                                               options: .AlignAllCenterY,
                                               metrics: nil,
                                               views: ["view":view, "subview":subview])

Instead of using VFL, you can easily do this in interface builder. In the Main Storyboard, ctrl+click on the view you want to center. Drag to the superview (while holding ctrl) and select "Center X" or "Center Y". No code needed.

참고URL : https://stackoverflow.com/questions/12873372/centering-a-view-in-its-superview-using-visual-format-language

반응형