[解決済み] プログラムによるCenterX/CenterY制約の追加
質問
UITableViewControllerを使用していますが、表示するものがない場合、セクションを表示しません。このコードで表示するものがないことをユーザーに示すためのラベルを追加しています。
label = UILabel(frame: CGRectMake(20, 20, 250, 100))
label.text = "Nothing to show"
self.tableView.addSubview(label)
しかし今度は、水平方向と垂直方向の中央揃えにしたいのです。通常、私はスクリーンショットで強調表示されている 2 つのオプション (高さと幅のオプション) を選択します。
以下のコードで制約を追加してみましたが、アプリがエラーでクラッシュしてしまいます。
label = UILabel(frame: CGRectMake(20, 20, 250, 100))
label.text = "Nothing to show"
let xConstraint = NSLayoutConstraint(item: label, attribute: .CenterX, relatedBy: .Equal, toItem: self.tableView, attribute: .CenterX, multiplier: 1, constant: 0)
let yConstraint = NSLayoutConstraint(item: label, attribute: .CenterY, relatedBy: .Equal, toItem: self.tableView, attribute: .CenterY, multiplier: 1, constant: 0)
label.addConstraint(xConstraint)
label.addConstraint(yConstraint)
のエラーが発生しました。
When added to a view, the constraint's items must be descendants of that view (or the view itself). This will crash if the constraint needs to be resolved before the view hierarchy is assembled. Break on -[UIView _viewHierarchyUnpreparedForConstraint:] to debug.
2014-12-23 08:17:36.755 [982:227877] *** Assertion failure in -[UILabel _layoutEngine_didAddLayoutConstraint:roundingAdjustment:mutuallyExclusiveConstraints:], /SourceCache/UIKit/UIKit-3318.16.21/NSLayoutConstraint_UIKitAdditions.m:560
デバイスの回転に対応しているため、ラベルは常に水平方向と垂直方向の中央に表示される必要があります。
何が間違っているのでしょうか。どうすればこれらの制約をうまく追加できますか。
ありがとうございます。
どのように解決するのですか?
Swift 3/Swift 4に対応したアップデートが必要です。
iOS 8 では、制約を有効にするには、制約の
isActive
プロパティを
true
. これにより、制約が適切なビューに追加されるようになります。 複数の制約を一度にアクティブにするには、制約を含む配列を
NSLayoutConstraint.activate()
let label = UILabel(frame: CGRect.zero)
label.text = "Nothing to show"
label.textAlignment = .center
label.backgroundColor = .red // Set background color to see if label is centered
label.translatesAutoresizingMaskIntoConstraints = false
self.tableView.addSubview(label)
let widthConstraint = NSLayoutConstraint(item: label, attribute: .width, relatedBy: .equal,
toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: 250)
let heightConstraint = NSLayoutConstraint(item: label, attribute: .height, relatedBy: .equal,
toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: 100)
let xConstraint = NSLayoutConstraint(item: label, attribute: .centerX, relatedBy: .equal, toItem: self.tableView, attribute: .centerX, multiplier: 1, constant: 0)
let yConstraint = NSLayoutConstraint(item: label, attribute: .centerY, relatedBy: .equal, toItem: self.tableView, attribute: .centerY, multiplier: 1, constant: 0)
NSLayoutConstraint.activate([widthConstraint, heightConstraint, xConstraint, yConstraint])
より良い解決策を
この質問が最初に回答されて以来、レイアウトアンカーが導入され、制約を作成するのがより簡単になりました。 この例では、私は制約を作成し、すぐにそれを有効にします。
label.widthAnchor.constraint(equalToConstant: 250).isActive = true
label.heightAnchor.constraint(equalToConstant: 100).isActive = true
label.centerXAnchor.constraint(equalTo: self.tableView.centerXAnchor).isActive = true
label.centerYAnchor.constraint(equalTo: self.tableView.centerYAnchor).isActive = true
あるいは,同じように
NSLayoutConstraint.activate()
:
NSLayoutConstraint.activate([
label.widthAnchor.constraint(equalToConstant: 250),
label.heightAnchor.constraint(equalToConstant: 100),
label.centerXAnchor.constraint(equalTo: self.tableView.centerXAnchor),
label.centerYAnchor.constraint(equalTo: self.tableView.centerYAnchor)
])
注意: サブビューは常にビュー階層に追加してください。 の前に を作成し、制約をアクティブにします。
オリジナルの回答です。
制約が参照するのは
self.tableView
. のサブビューとしてラベルを追加しているので、この制約は
self.tableView
のサブビューとしてラベルを追加しているので、制約は "共通の祖先" に追加される必要があります。
self.tableView.addConstraint(xConstraint)
self.tableView.addConstraint(yConstraint)
コメントで@mustafaさんや@kcstricksさんが指摘されているように、このような場合は
label.translatesAutoresizingMaskIntoConstraints
を
false
. これを行う場合、さらに
width
と
height
は、フレームが使用されなくなったので、制約を持つラベルの 最後に
textAlignment
を
.Center
に変更し、テキストがラベルの中央に配置されるようにします。
var label = UILabel(frame: CGRectZero)
label.text = "Nothing to show"
label.textAlignment = .Center
label.backgroundColor = UIColor.redColor() // Set background color to see if label is centered
label.translatesAutoresizingMaskIntoConstraints = false
self.tableView.addSubview(label)
let widthConstraint = NSLayoutConstraint(item: label, attribute: .Width, relatedBy: .Equal,
toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant: 250)
label.addConstraint(widthConstraint)
let heightConstraint = NSLayoutConstraint(item: label, attribute: .Height, relatedBy: .Equal,
toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant: 100)
label.addConstraint(heightConstraint)
let xConstraint = NSLayoutConstraint(item: label, attribute: .CenterX, relatedBy: .Equal, toItem: self.tableView, attribute: .CenterX, multiplier: 1, constant: 0)
let yConstraint = NSLayoutConstraint(item: label, attribute: .CenterY, relatedBy: .Equal, toItem: self.tableView, attribute: .CenterY, multiplier: 1, constant: 0)
self.tableView.addConstraint(xConstraint)
self.tableView.addConstraint(yConstraint)
関連
-
EXC_BAD_ACCESS (code=2, address=0x0)
-
[解決済み] Xcode 4で「既存のフレームワークを追加」する方法は?
-
[解決済み] iOSのバージョンを確認する方法を教えてください。
-
[解決済み] Objective-Cでデリゲートを作成するにはどうしたらいいですか?
-
[解決済み] Xcodeにおけるバージョンとビルドの比較
-
[解決済み] Xcode 12、iOS Simulator用にビルドしても、iOS用にビルドされたオブジェクトファイルでは、アーキテクチャ「arm64」用にリンクされます。
-
[解決済み] Swift 3, 4, 5 で dispatch_after GCD を書くにはどうしたらいいですか?
-
[解決済み] Swiftの配列を文字列に変換するには?
-
[解決済み】UIScrollView Scrollable Content Size Ambiguity
-
[解決済み] UIViewsを非表示にしたAutoLayout?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] iOSのステータスバーの文字色を変更する方法
-
[解決済み] UITableViewの下にある余分なセパレータをなくす
-
[解決済み] UIViewController のビューが表示されているかどうかを確認する方法
-
[解決済み] CocoaPodsの最新バージョンにアップデートしますか?
-
[解決済み] Swift 3, 4, 5 で dispatch_after GCD を書くにはどうしたらいいですか?
-
[解決済み] コア・データ エンティティの全インスタンスを削除する最短の方法
-
[解決済み] UIImageのサイズを変更する最も簡単な方法?
-
[解決済み] Swiftの配列を文字列に変換するには?
-
[解決済み] Swift 3でディスパッチキューを作成する方法
-
[解決済み] UITextBorderStyleNoneを使用してUITextFieldのパディングを設定する