2014-09-05 5 views
29

4 개의 버튼 레이아웃이 있습니다. 세로로 보면 서로 위에 하나씩 표시해야합니다. 가로 방향에서는 두 개의 열이 있고 두 개의 버튼이 있어야합니다.크기 클래스를 사용하여 프로그래밍 방식으로 두 개의 다른 레이아웃 구현

나는 코드에서 버튼을 구현 - 정말 간단한 물건을 :

UIButton *btn1 = [[UIButton alloc] init]; 
[self.view addSubview: btn1]; 

UIButton *btn2 = [[UIButton alloc] init]; 
[self.view addSubview: btn2]; 

UIButton *btn3 = [[UIButton alloc] init]; 
[self.view addSubview: btn3]; 

UIButton *btn4 = [[UIButton alloc] init]; 
[self.view addSubview: btn4]; 

NSDictionary *views = NSDictionaryOfVariableBindings(btn1, btn2, btn3, btn4); 

[btn1 setTranslatesAutoresizingMaskIntoConstraints:NO]; 
[btn2 setTranslatesAutoresizingMaskIntoConstraints:NO]; 
[btn3 setTranslatesAutoresizingMaskIntoConstraints:NO]; 
[btn4 setTranslatesAutoresizingMaskIntoConstraints:NO]; 

// portrait constraints 
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(50)-[btn1]-(50)-|" 
                   options:0 metrics:nil views:views]]; 
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(50)-[btn2]-(50)-|" 
                   options:0 metrics:nil views:views]]; 
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(50)-[btn3]-(50)-|" 
                   options:0 metrics:nil views:views]]; 
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(50)-[btn4]-(50)-|" 
                   options:0 metrics:nil views:views]]; 

[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[btn1]-[btn2]-[btn3]-[btn4]-(50)-|" 
                   options:0 metrics:nil views:views]]; 

이 분명 세로 레이아웃에 대한 설정입니다. 나는 각각의 방향에서 iPad와 iPhone을위한 특별한 경우를 만들기 위해 장치와 방향을 결정하는 데 익숙했습니다. 그러나 이제 우리는 크기 클래스를 사용하기로되어 있습니다. 크기 클래스가 "컴팩트"한지 어떻게 알 수 있습니까? 그러면 적절한 제약 조건을 설정할 수 있습니까?

답변

16

그동안 좋은 해결책을 발견했습니다. 이 질문에는 많은 상향 음절이 있기 때문에 나는 그것을 빨리 기술 할 것이라고 생각했다. WWDC 세션에서이 솔루션에 영감을 받았습니다.

저는 스위프트로 옮겼습니다. 코드가 신속히 처리 될 것이라고 생각하십시오. 그러나 개념은 Obj-C와 같습니다.

// Constraints 
private var compactConstraints: [NSLayoutConstraint] = [] 
private var regularConstraints: [NSLayoutConstraint] = [] 
private var sharedConstraints: [NSLayoutConstraint] = [] 

을 그리고 그에 따라 제약을 채우기 :

세 가지 제약 배열을 선언함으로써 시작합니다. 즉, viewDidLoad에서 전화를 걸거나 직접 viewDidLoad에서 전화하는 별도의 기능으로이 작업을 수행 할 수 있습니다.

sharedConstraints.append(contentsOf: [ 
    btnStackView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor), 
    ... 
]) 

compactConstraints.append(contentsOf: [ 
    btnStackView.widthAnchor.constraint(equalTo: self.view.widthAnchor, multiplier: 0.7), 
    ... 
]) 

regularConstraints.append(contentsOf: [ 
    btnStackView.widthAnchor.constraint(equalTo: self.view.widthAnchor, multiplier: 0.4), 
    ... 
]) 

중요한 부분은 크기 제한을 전환하고 적절한 제한 조건을 활성화/비활성화하는 것입니다.

override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { 

    super.traitCollectionDidChange(previousTraitCollection) 

    if (!sharedConstraints[0].isActive) { 
     // activating shared constraints 
     NSLayoutConstraint.activate(sharedConstraints) 
    } 


    if traitCollection.horizontalSizeClass == .compact && traitCollection.verticalSizeClass == .regular { 
     if regularConstraints.count > 0 && regularConstraints[0].isActive { 
      NSLayoutConstraint.deactivate(regularConstraints) 
     } 
     // activating compact constraints 
     NSLayoutConstraint.activate(compactConstraints) 
    } else { 
     if compactConstraints.count > 0 && compactConstraints[0].isActive { 
      NSLayoutConstraint.deactivate(compactConstraints) 
     } 
     // activating regular constraints 
     NSLayoutConstraint.activate(regularConstraints) 
    } 
} 

저는 제약 조건이 질문에 맞지 않는다는 것을 알고 있습니다. 그러나 제약 조건 자체는 부적합합니다. 중요한 것은 크기 클래스를 기반으로 두 가지 제약 조건 집합간에 전환하는 방법입니다.

희망이 도움이됩니다. 허용 대답에 대한

+0

ummm wwdc 세션이이게 뭐야? – Honey

33

보기의 특성 컬렉션을 검사하여 가로 및 세로 크기 클래스를 결정할 수 있습니다.

if (self.view.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClassCompact) { 
    ... 
} 

autorotation으로 인해 특성이 변경 될 때 traitCollectionDidChange: 메서드가 자동으로 호출되도록 구현합니다.

자세한 내용은 UITraitCollection Class ReferenceUITraitEnvironment Protocol Reference을 참조하십시오.

+0

하지만이 질문에 대답하지 않는다 - 나는 이미 코드에 제약을 선언 한 경우 지금은 다음 예를 들어, 세로 및 가로 아이폰 다를하려면 이 코드를 어떻게 수정해야합니까? –

+0

점검 로직은'viewWillLayoutSubviews()'에 위치해야합니다. – Protocole

0

traitCollection은 iOS8에서만 작동합니다. 따라서 iOS7에서 앱이 다운됩니다. 아래 코드를 사용하여 iOS7 및 iOS8을 모두 지원하십시오.

if ([self.view respondsToSelector:@selector(traitCollection)]){ 

    if (self.view.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClassCompact) { 
    ... 
    } 

} 
+3

질문에 'iOS8'태그가 지정되었습니다. – KPM

2

스위프트 4 코드 :

if (self.view.traitCollection.horizontalSizeClass == .compact) { 
... 
} 
확인