次の問題があります。カスタムUIView
クラスとそのレイアウトをXIB
ファイルに作成しました。 XIBでのカスタムビューのサイズが150 x 50であるとしましょう。sizeClasses
(wAny hAny)とAutoLayout
を有効にしました。シミュレートされたメトリックでは、Size = Freeform
、Status Bar = None
、 すべて other = Inferred
。
カスタムUIView
クラスのコードは次のようになります。
#import "CustomView.h"
@implementation CustomView
#pragma mark - Object lifecycle
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self setup];
}
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
[self setup];
}
return self;
}
#pragma mark - Private & helper methods
- (void)setup {
if (self.subviews.count == 0) {
[[NSBundle mainBundle] loadNibNamed:@"CustomView" owner:self options:nil];
self.bounds = self.view.bounds;
[self addSubview:self.view];
}
}
@end
このカスタムUIViewController
を追加するUIView
で、CustomView
を追加するダミーUIView(インターフェイスビルダーで設定したサイズ)を作成しました。 私のCustomView
が私のコンテナビューの境界に一致するようにしたい。
私はそれをこのようにしようとしています:
_vCustomView = [[CustomView alloc] init];
_vCustomView.translatesAutoresizingMaskIntoConstraints = NO;
[_vContainer addSubview:_vCustomView];
[_vContainer addConstraint:[NSLayoutConstraint constraintWithItem:_vCustomView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:_vContainer attribute:NSLayoutAttributeLeft multiplier:1.0 constant:0.0]];
[_vContainer addConstraint:[NSLayoutConstraint constraintWithItem:_vCustomView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:_vContainer attribute:NSLayoutAttributeRight multiplier:1.0 constant:0.0]];
[_vContainer addConstraint:[NSLayoutConstraint constraintWithItem:_vCustomView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:_vContainer attribute:NSLayoutAttributeTop multiplier:1.0 constant:0.0]];
[_vContainer addConstraint:[NSLayoutConstraint constraintWithItem:_vCustomView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:_vContainer attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0.0]];
しかし、運はありません。コンテナービューが300 x 100で、カスタムUIView
を追加すると、私のカスタムビューは150 x 5になります。
コンテナビューなしで作業を試みました-カスタムUIView
オブジェクトをUIViewController
のself.viewに直接追加し、幅と高さを次のように設定します。
autoLayout
制約initWithFrame
を使用するUIView
しかし再び-運はありません。カスタムビューは常に150 x 50です。
誰かが私にどのようにして私に説明できるかプログラムでUIView
で作成したカスタムXIB
を追加し、autoLayout
制約を使用してサイズ変更?
よろしくお願いします。
編集#1:CustomViewでAndreaのコードを実行しようとすると発生するエラー
Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints)
(
"<NSLayoutConstraint:0x17489b760 V:[UIView:0x17418d820(91)]>",
"<NSLayoutConstraint:0x170c9bf80 V:|-(0)-[CustomView:0x1741da7c0] (Names: '|':CustomView:0x1741da8b0 )>",
"<NSLayoutConstraint:0x170c9bfd0 V:[CustomView:0x1741da7c0]-(0)-| (Names: '|':CustomView:0x1741da8b0 )>",
"<NSLayoutConstraint:0x170c9be90 V:|-(0)-[CustomView:0x1741da8b0] (Names: '|':UIView:0x17418d820 )>",
"<NSLayoutConstraint:0x170c9bee0 CustomView:0x1741da8b0.bottom == UIView:0x17418d820.bottom>",
"<NSAutoresizingMaskLayoutConstraint:0x170c9dba0 h=--& v=--& CustomView:0x1741da7c0.midY == + 25.0>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x170c9bfd0 V:[CustomView:0x1741da7c0]-(0)-| (Names: '|':CustomView:0x1741da8b0 )>
編集#2:うまくいく!
@Andreaが追加した後:
view.translatesAutoresizingMaskIntoConstraints = NO;
彼の中で:
- (void) stretchToSuperView:(UIView*) view;
メソッド、すべてが期待どおりに機能します。
@Andreaに感謝します。
Xibをコンテンツビューに追加するときに自動レイアウトを使用しないことが主な問題だと思います。
initメソッドにサブビューを追加した後、そのメソッドを呼び出して、xibのビューを渡します。
- (void) stretchToSuperView:(UIView*) view {
view.translatesAutoresizingMaskIntoConstraints = NO;
NSDictionary *bindings = NSDictionaryOfVariableBindings(view);
NSString *formatTemplate = @"%@:|[view]|";
for (NSString * axis in @[@"H",@"V"]) {
NSString * format = [NSString stringWithFormat:formatTemplate,axis];
NSArray * constraints = [NSLayoutConstraint constraintsWithVisualFormat:format options:0 metrics:nil views:bindings];
[view.superview addConstraints:constraints];
}
}
[編集]
セットアップコードは次のようになります。
- (void)setup {
if (self.subviews.count == 0) {
[[NSBundle mainBundle] loadNibNamed:@"CustomView" owner:self options:nil];
self.bounds = self.view.bounds;
[self addSubview:self.view];
[self stretchToSuperView:self.view];
}
}
ストレッチビュー内に追加したことに注意してくださいview.translatesAutoresizingMaskIntoConstraints = NO;
[編集2]
リクエストに応じて、回答を詳しく説明します。 autolayoutを使用して、制約を設定せずにビューを追加すると、autolayoutは自動サイズ変更マスクを制約に自動的に変換し、それらのデフォルトプロパティはUIViewAutoresizingNone
です。つまり、自動サイズ変更しません。
あなたのXIBビューは、制約なしに、そして自動サイズ変更の可能性なしにその親に追加されたため、元のサイズを維持しています。ビューに合わせてビューのサイズを変更したいので、2つの選択肢があります。
後で行うことは、ビュー(XIBビューをホストする)にスーパービューに制約を追加することですが、XIBとその親の間に制約がなかったため、自動レイアウトではXIBビューのサイズを変更する方法がわかりません。
ビュー階層の各ビューには、独自の制約が必要です。
これが理解を深めるのに役立つことを願っています。
スーパービューに拡大するSwift 4.0関数:
コードスニペット:
static public func stretchToSuperView(view:UIView)
{
view.translatesAutoresizingMaskIntoConstraints = false
var d = Dictionary<String,UIView>()
d["view"] = view
for axis in ["H","V"] {
let format = "\(axis):|[view]|"
let constraints = NSLayoutConstraint.constraints(withVisualFormat: format, options: NSLayoutFormatOptions(rawValue: 0), metrics: [:], views: d)
view.superview?.addConstraints(constraints)
}
}
注:サブビューとして引数を指定して関数を呼び出すだけです。
これは、Swift 4.0の.xib resingの問題を解決するのに役立ちます。
あなたのコードには次のようなものが必要です:
まず、変更したい幅制約へのIBOutlet
を、viewControllerまたはCustomView
のどちらかで指定します(制約値を計算するためのロジックがどこにあるのか、実際にはわかりません)。
@property (nonatomic, weak) IBOutlet NSLayoutConstraint *widthConstraint;
次に、定数値を更新するメソッドで、次のようなものが得られます。
-(void)updateWidth {
[self.widthConstraint setConstant:newConstant];
[self.view layoutIfNeeded]; // self.view must be an ancestor of the view
//If you need the changes animated, call layoutIfNeeded in an animation block
}
これがうまくいくことを願っています。幸運を!