2014-09-05 13 views
29

У меня есть четыре макета кнопок. В портрете они должны быть показаны один над другим. В ландшафте они должны быть в двух столбцах с двумя кнопками.Программная реализация двух разных макетов с использованием классов размера

я реализую кнопки в коде - очень простые вещи:

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.

Я перешел к Swift, поэтому, пожалуйста, извините за то, что код будет быстрым - концепция, тем не менее, одинакова для 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) { 
    ... 
} 

реализовать метод traitCollectionDidChange: автоматически вызывается, когда черта изменяется из-за авторотации.

Для получения дополнительной информации см. UITraitCollection Class Reference и UITraitEnvironment Protocol Reference.

+0

нормально, но это не дает ответа на вопрос - если я уже объявил ограничения в коде, и теперь я хочу, чтобы отличаться, например, портретной и ландшафтной Iphone затем как я должен исправить этот код? –

+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

Swift 4 код принятого ответа:

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

 Смежные вопросы

  • Нет связанных вопросов^_^