4つのボタンレイアウトがあります。ポートレートでは、上下に表示する必要があります。ランドスケープでは、それぞれ2つのボタンがある2つの列になります。
コードにボタンを実装します-本当にシンプルなもの:
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のそれぞれの向きで特定のケースを作成するために、デバイスとその向きを決定していました。しかし、今はサイズクラスを使用することになっています。サイズクラスが「コンパクト」であるかどうかを判断し、適切な制約を設定するにはどうすればよいですか?
それまでの間、私は良い解決策を見つけました。この質問には非常に多くの賛成票があるため、すぐに説明すると思いました。 WWDCセッションからこのソリューションに触発されました。
Swiftに移動したので、コードはSwift-Obj-Cでも概念は同じです。
まず、3つの制約配列を宣言することから始めます。
// 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)
}
}
私は、制約が問題の制約に適合しないことを知っています。しかし、制約自体は無関係です。主なことは、サイズクラスに基づいて2組の制約を切り替える方法です。
お役に立てれば。
ビューの特性コレクションを調べて、水平および垂直サイズクラスを決定できます。
if (self.view.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClassCompact) {
...
}
traitCollectionDidChange:
メソッドは、自動回転により特性が変化したときに自動的に呼び出されます。
詳細については、「 ITraitCollection Class Reference 」および「 ITraitEnvironment Protocol Reference 」を参照してください。
受け入れられた答えのSwift 4コード:
if (self.view.traitCollection.horizontalSizeClass == .compact) {
...
}
traitCollectionはiOS8でのみ機能します。そのため、アプリはiOS7でクラッシュします。以下のコードを使用して、iOS7とiOS8の両方をサポートします
if ([self.view respondsToSelector:@selector(traitCollection)]){
if (self.view.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClassCompact) {
...
}
}