NSLayoutConstraints и динамическая установка ширины/высоты представления
У меня вопрос о настройке размера представления, к которому я применяю некоторые ограничения макета.
Как определить размер представления без определения его фрейма?
Я пытаюсь создать представление с фиксированной высотой и имеет начало координат на экране. Он заполняет ширину вида, так что, когда устройство вращается, вид расширяется до ширины экрана. Это то, что у меня есть до сих пор...
self.containerView = [[HitTestContainerView alloc] init];
[self.containerView setBackgroundColor:[UIColor redColor]];
[self.view addSubview:self.containerView];
NSDictionary *viewsDictionary = @{@"view":self.containerView};
NSArray *verticalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-50-[view]-250-|" options:0 metrics:nil views:viewsDictionary];
NSArray *horizontalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[view]|" options:0 metrics:nil views:viewsDictionary];
[self.view addConstraints:verticalConstraints];
[self.view addConstraints:horizontalConstraints];
Проблема заключается в том, что я не могу ничего отобразить на экране, если не установить фрейм этого containerView
. Каков правильный способ сделать это без использования Interface Builder?
Ответы
Ответ 1
Чтобы определить высоту и ширину представления с использованием ограничений макета, вы определяете высоту и ширину представления с использованием ограничений макета. Например, вы уже говорите:
NSArray *verticalConstraints =
[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-50-[view]-250-|"
options:0 metrics:nil views:viewsDictionary];
Итак, вы можете просто изменить это:
NSArray *verticalConstraints =
[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(50)-[view(40)]"
options:0 metrics:nil views:viewsDictionary];
Теперь представление будет 50 пикселей от вершины его супервизора и 40 пикселей в высоту.
В качестве альтернативы вы можете использовать constraintWithItem:attribute:relatedBy:toItem:attribute:multiplier:constant:
для установки ограничения высоты; toItem
будет, конечно, нулевым, так как нет отношения к другому виду.
Ответ 2
Я написал небольшой инструмент, который поможет вам в этом:
http://autolayoutconstraints.com
Вот ответ на ваш вопрос, автогенерируемый инструментом
Objective-C
// align view from the left and right
[self.containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-10-[view]-10-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(view)]];
// width constraint
[self.containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[view(==250)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(view)]];
// height constraint
[self.containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[view(==50)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(view)]];
Swift
// align view from the left and right
self.containerView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-10-[view]-10-|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["view": view]));
// width constraint
self.containerView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:[view(==250)]", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["view": view]));
// height constraint
self.containerView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:[view(==50)]", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["view": view]));
Ответ 3
Лучше позже, чем никогда...
Для раскадровки, IB и Swift:
Просто управляйте, перетащите свое ограничение, как и любой другой элемент управления, в свой диспетчер viewController
@IBOutlet weak var spaceToTopThatIDecided: NSLayoutConstraint!
то просто измените его:
spaceToTopThatIDecided.constant = 44
Что все!
Ответ 4
вам не нужно использовать методы addConstraints:()
- (void)addConstraint:(NSLayoutConstraint *)constraint NS_AVAILABLE_MAC(10_7);
//Этот метод устарел и его следует избегать. Вместо этого установите для свойства NSLayoutConstraint значение YES.
- (void)addConstraints:(NSArray *)constraints NS_AVAILABLE_MAC(10_7);
//Этот метод устарел и его следует избегать. Вместо этого используйте
+[NSLayoutConstraint activateConstraints:].
//поэтому нужно использовать
+ (void)activateConstraints:(NSArray *)constraints NS_AVAILABLE(10_10, 8_0);
//затем установите значение
NSView *view,*containerView;
view =//superview
containerView=//subview
[view addSubview:containerView];
//добавление ограничений
[containerView setTranslatesAutoresizingMaskIntoConstraints:NO];
//об этом читаем из документации Apple
//затем добавьте ограничения типа
[NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-50-[view]-50-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(containerView)]];
[NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[view]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(containerView)]];
//thats it.
Ответ 5
Swift 4:
Вы можете управлять шириной и высотой в дополнение к ведущему, охватывающему и верхнему и нижнему пространству только с помощью двух опций
//1 . left and right spacing
theContentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-16-[view]-16-|", options:NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["view":nibView]))
//2. top and bottom spacing
theContentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-16-[view]-16-|", options:NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["view":nibView]))
ИЛИ
Чтобы быть более конкретным и иметь отдельные ограничения для W, H, левого интервала, верхнего интервала, вы можете сделать, как показано ниже
//left only spacing
theContentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-16-[view]", options:NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["view":nibView]))
//top only spacing
theContentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-16-[view]", options:NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["view":nibView]))
//width
theContentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:[view(==130)]", options:NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["view":nibView]))
//height
theContentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:[view(==100)]", options:NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["view":nibView]))