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

비즈니스 로직에 따라 UIViews가장 자주 표시 / 숨기는 것이 일반적인 패러다임 인 것 같습니다 UILabels. 내 질문은 AutoLayout을 사용하여 프레임이 0x0 인 것처럼 숨겨진 뷰에 응답하는 가장 좋은 방법은 무엇입니까? 다음은 1-3 개의 기능으로 구성된 동적 목록의 예입니다.

동적 기능 목록

지금은 버튼에서 마지막 레이블까지 10px의 상단 공간이 있으며 레이블이 숨겨져 있으면 분명히 미끄러지지 않습니다. 지금 까지이 제약 조건에 대한 콘센트를 만들고 표시하는 레이블 수에 따라 상수를 수정했습니다. 음수 상수 값을 사용하여 숨겨진 프레임 위로 버튼을 밀어 올리므로 분명히 해킹입니다. 실제 레이아웃 요소에 구속되지 않고 다른 요소의 알려진 높이 / 패딩을 기반으로 몰래 정적 계산을 수행하고 AutoLayout이 만들어진 것과 분명히 싸우기 때문에 나쁘다.

동적 레이블에 따라 새로운 제약 조건을 만들 수는 있지만 공백을 축소하려고 시도하는 것에 대한 많은 미세 관리 및 자세한 표시입니다. 더 나은 접근 방법이 있습니까? 프레임 크기 0,0을 변경하고 AutoLayout이 제약 조건을 조작하지 않고 그 일을 수행하게합니까? 뷰를 완전히 제거 하시겠습니까?

솔직히, 숨겨진보기의 컨텍스트에서 상수를 수정하면 간단한 계산으로 한 줄의 코드가 필요합니다. 새로운 제약 조건을 재현하는 constraintWithItem:attribute:relatedBy:toItem:attribute:multiplier:constant:것은 너무 무거워 보입니다.

2018 년 2 월 편집 : UIStackViews로 Ben의 답변보기



답변

UIStackView아마도 iOS 9 이상으로가는 길일 것입니다. 숨겨진보기를 처리 할뿐만 아니라 올바르게 설정된 경우 추가 간격과 여백도 제거합니다.


답변

뷰를 표시하거나 숨기는 데 개인적으로 선호하는 것은 적절한 너비 또는 높이 제약 조건으로 IBOutlet을 만드는 것입니다.

그런 다음 constant값을 업데이트하여 0숨기거나 값을 표시해야합니다.

이 기술의 가장 큰 장점은 상대 구속 조건이 유지된다는 것입니다. 예를 들어 가로 간격이 x 인 뷰 A와 뷰 B가 있다고 가정 해 봅시다 . 뷰 A 너비 constant가로 설정 되면 뷰 0.fB가 왼쪽으로 이동하여 해당 공간을 채 웁니다.

제약 조건을 추가하거나 제거 할 필요가 없습니다. 이는 무거운 작업입니다. 제약 조건을 간단히 업데이트하면 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


답변

이 경우 Author 레이블의 높이를 적절한 IBOutlet에 매핑합니다.

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

구속 조건의 높이를 0.0f로 설정하면 재생 버튼의 높이가 허용하기 때문에 “패딩”을 유지합니다.

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

여기에 이미지 설명을 입력하십시오


답변

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

Jorge Arimany와 TMin의 대답과 비슷한 두 가지 제약 조건을 설정하십시오.

여기에 이미지 설명을 입력하십시오

표시된 세 제약 조건 모두 상수 값이 동일합니다. A1 및 A2로 표시된 제약 조건의 우선 순위는 500으로 설정되어 있고 B로 표시된 제약 조건의 우선 순위는 250 (또는 UILayoutProperty.defaultLow코드)으로 설정되어 있습니다.

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

constraintB.priority = .defaultHigh

그러나 요소가 표시되면 우선 순위를 다시 낮음 (250)으로 설정하십시오.

constraintB.priority = .defaultLow

isActive구속 조건 B를 변경 하는 것보다이 방법의 장점은 (사소하게도) 다른 방법으로 과도 요소가 뷰에서 제거되는 경우에도 여전히 구속 조건이 있다는 것입니다.


답변

뷰를 서브 클래 싱하고 재정의 func intrinsicContentSize() -> CGSize합니다. CGSizeZero보기가 숨겨져 있으면 돌아 오십시오 .


답변

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

이 사실 / 버그를 알면 일부 사람들이 레이아웃을 단순화하는 데 도움이 될 수 있습니다. 아마도 원래 질문의 레이아웃조차도 게시 할 것이라고 생각했습니다.