programing

숨겨진 UIView가 있는 자동 레이아웃?

skycolor 2023. 4. 22. 09:10
반응형

숨겨진 UIView가 있는 자동 레이아웃?

숨기거나 하다'는 것이 인 것 요.UIViews의 경우, 「」입니다.UILabels비즈니스 논리에 따라 달라집니다.AutoLayout을 사용하여 숨겨진 뷰에 프레임이 0x0인 것처럼 응답하는 가장 좋은 방법은 무엇입니까?은 1~ 기능의 입니다.1~3가지 기능

동적 기능 목록

현재 버튼에서 마지막 라벨까지 10px의 상단 공간이 있습니다.라벨이 숨겨져 있으면 확실히 위로 미끄러지지 않습니다.현시점에서는 이 제약에 대한 콘센트를 작성하고 표시하는 라벨의 수에 따라 상수를 변경합니다.숨겨진 프레임 위로 버튼을 누르기 위해 음의 상수 값을 사용하고 있기 때문에, 이것은 분명히 좀 허술합니다.또, 실제의 레이아웃 요소에 한정되지 않고, 기존의 높이나 다른 요소의 패딩에 근거해 교묘하게 정적인 계산을 실시해, Auto Layout이 구축되고 있는 목적에 대항하고 있기 때문에, 단점이 있습니다.

동적 레이블에 따라 새로운 제약 조건을 만들 수 있지만, 공백 공간을 축소하기 위해 많은 세밀한 관리와 장황함이 필요합니다.더 나은 방법이 있을까요?프레임 크기를 0,0으로 변경하고 제약 조건을 조작하지 않고 AutoLayout에서 작업을 수행할 수 있도록 하려면?보기를 완전히 제거하시겠습니까?

단, 숨김 뷰의 컨텍스트에서 상수를 수정하는 것만으로 간단한 계산을 통해 한 줄의 코드가 필요합니다.「」를 사용한 새로운 constraintWithItem:attribute:relatedBy:toItem:attribute:multiplier:constant:너무 무거워 보여요.

2018년 2월 편집: Ben의 답변을 참조하십시오.UIStackViews

뷰 표시/숨김을 개인적으로 선호하는 것은 적절한 폭 또는 높이 제한을 가진 IBOutlet을 작성하는 것입니다.

하겠습니다.constant을 매기다0숨길 수 있는지, 또는 그 값을 보여줘야 하는지.

이 기술의 큰 장점은 상대적인 제약이 유지된다는 것입니다.예를 들어 뷰 A와 뷰 B를 수평 간격 x로 표시한다고 가정합니다.A폭을 볼 때constant로 설정되어 있다.0.fB-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-

무거운 작업인 구속조건을 추가하거나 제거할 필요가 없습니다. 됩니다.constant효과가 있을 거야

0숨겼을 때 다른 상수를 다시 표시하면 기능하지만 컨텐츠의 크기가 유연한 경우에는 만족스럽지 않습니다.유연한 컨텐츠를 측정하여 일정하게 되돌려야 합니다.이는 잘못된 것으로 느껴지며 서버 또는 UI 이벤트로 인해 컨텐츠 크기가 변경될 경우 문제가 발생합니다.

내게 더 좋은 해결책이 있어

이 방법은 요소를 숨길 때 0 높이 규칙을 높은 우선순위로 설정하여 요소가 자동 레이아웃 공간을 차지하지 않도록 하는 것입니다.

그 방법은 다음과 같습니다.

1. 우선도가 낮은 인터페이스 빌더에서 폭(또는 높이)을 0으로 설정합니다.

폭 0 규칙 설정

우선순위가 낮기 때문에 Interface Builder는 충돌에 대해 소리치지 않습니다.우선 순위를 일시적으로 999로 설정하여 높이 동작을 테스트합니다(1000은 프로그래밍 방식으로 변환하는 것이 금지되므로 사용하지 않습니다).인터페이스 빌더는 아마도 모순되는 제약조건에 대해 고함을 지르게 될 것입니다.관련 객체의 우선순위를 900 정도로 설정하면 이러한 문제를 해결할 수 있습니다.

2. 코드에서 너비 제약의 우선순위를 변경할 수 있도록 콘센트를 추가합니다.

콘센트 접속

3. 요소를 숨길 때 우선순위를 조정합니다.

cell.alertTimingView.hidden    = place.closingSoon != true
cell.alertTimingWidth.priority = place.closingSoon == true ? 250 : 999

UIStackView 아마도 iOS 9+를 위한 방법일 것입니다.숨겨진 보기를 처리할 뿐만 아니라 올바르게 설정되면 추가 간격과 여백도 제거됩니다.

이 경우 작성자 라벨의 높이를 적절한 IBOutlet에 매핑합니다.

@property (retain, nonatomic) IBOutlet NSLayoutConstraint* authorLabelHeight;

그리고 구속의 높이를 0.0f로 설정하면 재생 버튼의 높이를 사용할 수 있기 때문에 패딩이 유지됩니다.

cell.authorLabelHeight.constant = 0; //Hide 
cell.authorLabelHeight.constant = 44; //Show

여기에 이미지 설명 입력

여기에는 많은 솔루션이 있지만, 일반적인 접근 방식은 또 다릅니다.

Jorge Arimany 및 TMin의 답변과 유사한 두 가지 제약 조건을 설정합니다.

여기에 이미지 설명 입력

표시된 세 개의 제약 조건은 모두 상수 값이 동일합니다.되어 있으며, B의 A1의 A2의 priority)으로 되어 .UILayoutProperty.defaultLow암호화되어 있습니다).

제약 B를 IBOutlet에 연결합니다.그런 다음 요소를 숨길 때 제약 조건 우선 순위를 높음(750)으로 설정하면 됩니다.

constraintB.priority = .defaultHigh

그러나 요소가 보이면 우선 순위를 다시 낮음(250)으로 설정합니다.

constraintB.priority = .defaultLow

(은 단순히 변경하기 위한 isActive제약 조건 B의 경우 과도 요소가 다른 방법으로 뷰에서 제거되는 경우에도 여전히 작동 제약 조건이 있습니다.

" " " 를 덮어씁니다.func intrinsicContentSize() -> CGSize 돌아와.CGSizeZero★★★★★★★★★★★★★★★★★★★★★★★★★★★

UILabel이 공간을 차지하지 않도록 하려면 UILabel을 숨기고 텍스트를 빈 문자열로 설정해야 한다는 것을 방금 알게 되었습니다.(iOS 9)

이 사실/버그를 알면 어떤 사람들은 레이아웃을 단순화할 수 있고, 심지어 처음 질문의 레이아웃도 단순화할 수 있기 때문에 게시하려고 합니다.

우아한 .UIKit이 바람직한 동작에 대응합니다.할 수 있기를 바라는 것은 매우 흔한 일인 것 같다.

의 접속 이 있기 때문에IBOutlets를 ㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴ0NSLayoutConstraint뷰에 서브뷰가 있는 경우 경고) 자동 레이아웃 제약이 있는를 숨기거나 표시하는 간단한 상태 저장 접근 방식을 제공하는 확장을 작성하기로 결정했습니다.

뷰를 숨기고 외부 구속조건을 제거합니다.보기를 다시 표시하면 제약 조건이 다시 추가됩니다.유일한 경고는 주변 뷰에 유연한 페일오버 제약을 지정해야 한다는 것입니다.

편집 이 답변은 iOS 8.4 이하를 대상으로 합니다.iOS 9에서는UIStackView★★★★★★ 。

는 모든 있는 경우 에 조건을 IBOutlet★★★★★★★★★★★★★★★★★★.

속성이 다음 중 하나인지 확인합니다.strong

코드에서는 상수를 0으로 설정하고 활성화하거나 내용을 숨기거나 비활성화하여 내용을 표시하면 됩니다.이 방법은 일정 값을 잘못 사용하여 저장 복구하는 것보다 낫습니다.잊지 말고 전화하세요layoutIfNeeded★★★★★★★★★★★★★★★★★★.

숨길 내용이 그룹화되어 있는 경우 모든 내용을 뷰에 넣고 해당 뷰에 제약을 추가하는 것이 가장 좋습니다.

@property (strong, nonatomic) IBOutlet UIView *myContainer;
@property (strong, nonatomic) IBOutlet NSLayoutConstraint *myContainerHeight; //should be strong!!

-(void) showContainer
{
    self.myContainerHeight.active = NO;
    self.myContainer.hidden = NO;
    [self.view layoutIfNeeded];
}
-(void) hideContainer
{
    self.myContainerHeight.active = YES;
    self.myContainerHeight.constant = 0.0f;
    self.myContainer.hidden = YES;
    [self.view layoutIfNeeded];
}

설정이 완료되면 제약조건을 0으로 설정한 후 원래 값으로 되돌리는 방법으로 Interface Builder에서 테스트할 수 있습니다.다른 제약사항의 우선순위를 확인하는 것을 잊지 마십시오. 숨겨져 있어도 충돌이 발생하지 않도록 하십시오.테스트하는 다른 방법은 0으로 설정하고 priority를 0으로 설정하는 것입니다만, 다시 가장 높은 priority로 복원하는 것을 잊지 말아 주세요.

다음과 같이 카테고리를 구축하여 제약조건을 쉽게 업데이트합니다.

[myView1 hideByHeight:YES];

답변은 이쪽:Hide autolayout UIView : 기존 NSLayout Constraint를 가져와 이 NSLayout Constraint를 업데이트하는 방법

여기에 이미지 설명 입력

제가 선호하는 방법은 Jorge Arimany가 제안한 방법과 매우 유사합니다.

저는 여러 제약 조건을 만드는 것을 선호합니다.먼저 두 번째 라벨이 표시될 때를 위한 구속조건을 작성합니다.버튼과 두 번째 라벨 사이에 구속을 위한 콘센트를 만듭니다(objc를 사용하는 경우 강하게 해야 합니다).이 구속조건은 버튼이 표시될 때 버튼과 두 번째 라벨 사이의 높이를 결정합니다.

그런 다음 두 번째 버튼이 숨겨질 때 버튼과 상단 레이블 사이의 높이를 지정하는 다른 구속조건을 작성합니다.두 번째 구속조건에 대한 콘센트를 만들고 이 콘센트에 강한 포인터가 있는지 확인합니다. 다음 '보다 낫다'의 합니다.installed체크박스를 켜고 첫 번째 제약조건의 우선순위가 두 번째 제약조건 우선순위보다 낮은지 확인합니다.

으로 두 라벨을 때 " " "를 합니다..isActive 조건의 및 콜 " " " " " "setNeedsDisplay()

매직넘버나 계산은 필요 없습니다.온/오프해야 하는 제약이 여러 개 있는 경우에는 콘센트 컬렉션을 사용하여 주별로 정리할 수도 있습니다.(AKA는 1개의 Outlet Collection에 숨겨진 제약조건과 숨기지 않은 제약조건을 모두 다른 Outlet Collection에 유지하고 각 컬렉션에서 반복하여 .isActive 상태를 전환합니다).

Ryan Romanchuk이 여러 제약을 사용하고 싶지 않다고 말한 것은 알고 있습니다만, 이것은 세세한 부분까지가 아니고, 프로그래밍 방식으로 뷰와 제약을 동적으로 작성하는 것이 보다 단순하다고 생각합니다(이것은, 질문을 올바르게 읽고 있다면 피하고 싶었던 것이라고 생각합니다).

제가 간단한 예를 하나 만들었는데요, 유용했으면 좋겠는데...

import UIKit

class ViewController: UIViewController {

    @IBOutlet var ToBeHiddenLabel: UILabel!


    @IBOutlet var hiddenConstraint: NSLayoutConstraint!
    @IBOutlet var notHiddenConstraint: NSLayoutConstraint!


    @IBAction func HideMiddleButton(_ sender: Any) {

        ToBeHiddenLabel.isHidden = !ToBeHiddenLabel.isHidden
        notHiddenConstraint.isActive = !notHiddenConstraint.isActive
        hiddenConstraint.isActive = !hiddenConstraint.isActive

        self.view.setNeedsDisplay()
    }
}

여기에 이미지 설명 입력

저도 해결책을 제시하겠습니다.다양성을 제공하기 위해) 각 아이템의 너비/높이 플러스 간격에 콘센트를 설치하는 것은 터무니없고 코드, 가능한 오류 및 복잡함을 날려버립니다.

내 메서드는 모든 뷰(내 경우 UIImageView인스턴스)를 삭제하고 추가할 뷰를 선택하여 루프에서 각 뷰를 다시 추가하고 새로운 제약조건을 만듭니다.사실 정말 간단해요, 끝까지 따라오세요.빠르고 지저분한 코드입니다.

// remove all views
[self.twitterImageView removeFromSuperview];
[self.localQuestionImageView removeFromSuperview];

// self.recipients always has to be present
NSMutableArray *items;
items = [@[self.recipients] mutableCopy];

// optionally add the twitter image
if (self.question.sharedOnTwitter.boolValue) {
    [items addObject:self.twitterImageView];
}

// optionally add the location image
if (self.question.isLocal) {
    [items addObject:self.localQuestionImageView];
}

UIView *previousItem;
UIView *currentItem;

previousItem = items[0];
[self.contentView addSubview:previousItem];

// now loop through, add the items and the constraints
for (int i = 1; i < items.count; i++) {
    previousItem = items[i - 1];
    currentItem = items[i];

    [self.contentView addSubview:currentItem];

    [currentItem mas_remakeConstraints:^(MASConstraintMaker *make) {
        make.centerY.equalTo(previousItem.mas_centerY);
        make.right.equalTo(previousItem.mas_left).offset(-5);
    }];
}


// here I just connect the left-most UILabel to the last UIView in the list, whichever that was
previousItem = items.lastObject;

[self.userName mas_remakeConstraints:^(MASConstraintMaker *make) {
    make.right.equalTo(previousItem.mas_left);
    make.leading.equalTo(self.text.mas_leading);
    make.centerY.equalTo(self.attachmentIndicator.mas_centerY);;
}];

깔끔하고 일관된 레이아웃과 간격을 얻을 수 있습니다.제 코드는 Masonry를 사용하고 있습니다.강력히 추천합니다.https://github.com/SnapKit/Masonry

Box View를 사용해 보십시오.동적인 레이아웃을 간결하고 읽기 쉽게 만듭니다.
고객의 경우는 다음과 같습니다.

    boxView.optItems = [
        firstLabel.boxed.useIf(isFirstLabelShown),
        secondLabel.boxed.useIf(isSecondLabelShown),
        button.boxed
    ]

언급URL : https://stackoverflow.com/questions/19561269/autolayout-with-hidden-uiviews

반응형