2013-06-17 3 views
3

실제로 자동 레이아웃에 대해 나에게 미안한 점이 하나 있습니다. 테스트를 수행 중이며 UIView를 서브 클래스로 만들고 해당 제약 조건을 가진 뷰를 작성할 수 없다는 것을 알았습니다 계산 된 값을 알아라.
UIView에서 상속받은 TestViewClass가 있다고 가정 해 봅시다. 내부에 몇 개의 하위 뷰가 있습니다. 우리는 iPhone 및 iPad 용으로 사용하기를 원하므로 두 가지 크기로 사용합니다. 100x100 및 200x200 크기로 가정 해 봅시다. 우리는이 뷰를 빌드하여 일부 위치에 서브 뷰를 배치합니다.
이제 서브 뷰 (contentView)로 여러 개의 버튼이 포함 된 다른 서브 뷰를 빌드해야합니다.이 서브 뷰는 런타임에 제공됩니다.
알고리즘은이 콘텐츠보기의 크기를 선택하고 서로 동일한 거리에 있지만 전체 콘텐츠보기 너비를 포함하는 방식으로 단추 사이의 공백을 계산하는 정확한 수의 단추를 넣습니다. 예를 들어, contentView의 폭은 200 포인트이고, 버튼은 3이며, 한 변이 60 인 제곱입니다. 함께 180 개이므로 20 포인트 남았습니다. 버튼 사이의 간격은 10 포인트 이상이어야합니다.
자동 레이아웃이 적용되기까지 수천 번 번거 롭습니다. 그렇게하려면 superview 크기에 따라 너비를 조정하는 superview에 대한 몇 가지 제약 조건이있는 contentView의 너비가 필요합니다. 문제는 UIView 구현 내에서 최종 값을 얻을 수있는 위치를 찾을 수 없다는 것입니다. contentView의 사이즈
나는 시도했다 -layoutSubviews, -updateConstraints, -didMoveToSuperview, 가치 쇼는 항상 원래 것이다. 새 프레임이 계산되면?
나는 분명히



내가 그들을 독립적으로 테이블 뷰의 크기에 따라 화면에 모두 표시하기 위해 노력하고, 테이블 뷰 셀 높이를 설정하려고이 문제를 발견 ... 자동 레이아웃에 대해 뭔가를하지 않았다. 여기에 관련된 질문이 있습니다 other questionAutolayout보기에서 계산 된 값을 얻는 방법

+1

보기 컨트롤러의 'viewDidLayoutSubviews'에서'frame' 값을 확인해 보았습니까? – Rob

+0

안녕하세요 롭, 나는 그들이 개인 속성 때문에 보이지 않았다. 그래서 보이지 않는다. .. 비록 그들이 정확하다해도 나는 그들을 서브 클래스 안에서 잡아야한다. – Andrea

답변

9

마지막으로 나는 자동 레이아웃에 대해 놓친 것을 얻었으며 기본 개념입니다. 자동 레이아웃은 마스크를 자동 크기처럼 작동하지 않습니다

, 새로운 프레임은 즉시하지만 요청에 의해 업데이트되지 있습니다.이 큰 차이를 만들어

, 레이아웃 계산이 비싼 작업이 될 수 있기 때문에, 이해하게 CATransaction 렌더링주기와 동기화 될 것으로 보인다 그리고 당신이 정말로 그것을 필요로 할 때까지 할 쓸모가 대부분 렌더링 중의 시간
물론 예외는 거의 없으며 자동 레이아웃을 통해이 계산을 수행 할 수 있습니까? -setNeedsLayout 방법과 -layoutIfNeeded을 설정할 수 있습니다. 첫 번째 방법은보기를 "더티"로 표시하고 두 번째 방법은보기를 즉시 적용합니다. 올바른 업데이트 된 프레임을 얻은 직후 -didMoveToSuperview에 두 가지 방법을 호출하면됩니다.
호프가 도움이 되었으면 좋겠다. Andrea

+0

큰 설명 주셔서 감사합니다. 2 년 후, 다른 구현에서 동일한 문제를 해결할 수있었습니다. –

2

보기 컨트롤러의 viewDidLayoutSubviews을 사용하면보기가 배치되었을 때 사용자에게 알릴 수 있습니다. 이 모든 것이 사용자 정의 UIView에서 제약 조건 추가가 발생하면 viewDidLayoutSubviews이라는보기에 대한 메소드를 작성하고보기 컨트롤러가보기 컨트롤러가이를 수신 할 때 호출 할 수 있습니다. 이 시점에서 컨테이너의 크기는 올바르게 구성되어야합니다.

그러나, 심지어 컨테이너 뷰의 크기를 알고 귀찮게 할 필요없이 버튼의 무리 간격의 접근 방법의 몇 가지가 있습니다 :

  1. 한 가지 방법 나는 심지어 간격 제어를 위해 사용했습니다은 컨테이너는 내가 "스페이서"뷰 (현재있는 뷰이지만 단지 배경이 clearColor이므로 시각적으로 볼 수는 없다)를 생성하는 것입니다. 버튼의 전화 번호가 고정되어있는 경우

    H:|[spacer1][button1(60)][spacer2(==spacer1)][button2(60)][spacer3(==spacer1)][button3(60)][spacer4(==spacer1)]| 
    

    , 당신은 위와 같이, 하나의 constraintsWithVisualFormat에서이 작업을 수행 할 수 있습니다 : 당신은 효과적으로 사용 제약의 일련의 같은 것을 만들 수 있습니다. 가변 개수의 버튼이라면 버튼과 스페이서의 각 쌍에 대해 VFL 문자열을 작성하여 반복 할 수 있습니다 (예 :첫 번째 단추는 다음과 VFL을 다른 버튼과 다른 스페이서를 만들고 사용하는 것이

    H:|[spacer][button(60)] 
    

    이후의 모든 사람의 VFL을 사용합니다 :

    H:[previousButton][spacer(==originalSpacer)][button(60)] 
    

    을하고 난 끝에 마지막으로 스페이서를 추가

    H:[lastButton][spacer(==originalSpacer)]| 
    

    이 작업은 약간 번거롭지 만 컨트롤은 완벽하게 배치되어 있으며 균등하게 배치되어 있으므로 컨테이너의 크기를 알 필요가 전혀 없습니다.

  2. 또 다른 접근법은 NSLayoutFormatAlignAllCenterX 속성을 사용하는 것입니다. 이렇게하면 모든 스페이서를 만들 필요가 없지만 아래처럼 간단한 알고리즘을 사용하면 센터가 균등하게 분산됩니다. 따라서, 표준 수직 제약과 버튼의 수평 너비 제약 조건 이외에, 당신은 다음과 버튼의 수평 위치 제어 할 수 있습니다 i가의 제로로부터 시작되는 인덱스입니다

    [containerView addConstraint:[NSLayoutConstraint constraintWithItem:button[i] 
                      attribute:NSLayoutAttributeCenterX 
                      relatedBy:NSLayoutRelationEqual 
                      toItem:containerView 
                      attribute:NSLayoutAttributeCenterX 
                     multiplier:2.0 * (double) (i + 0.5)/(double) n 
                      constant:0.0]]; 
    

    을하는 버튼을 ' 에 대해이 수평 구속 조건을 다시 설정하고 n은 버튼 수입니다.

+0

스페이서보기를 숨김으로 설정할 수도 있습니다. 숨겨진보기가 레이아웃에 참여합니다. –

+0

@robmayoff 동의 함. 또는 '알파'를 0으로 설정하십시오. 거기에 여러 가지 옵션이 있습니다. 감사! – Rob

+1

안녕하세요, 감사합니다. 감사합니다. 감사합니다. 귀중한 답변입니다. 투표를했으나 중요한 것은 아닙니다. 나는 내가 알아 낸 것 같아. 감사합니다 – Andrea

관련 문제