Ограничения макета элемента UIView
Я довольно новичок в разработке под iOS, но дошел до того, что хочу создать свой собственный составной UIView в качестве пользовательской кнопки UIB. Я хотел бы расположить UILabel и 2x UIImageViews следующим образом;
Но я также хотел бы закрепить элементы управления (подпредставления) таким образом, чтобы при расширении метки, например, из-за переводов, представление автоматически обрабатывало дополнительные объекты. Например;
В идеале -
- правая сторона UIView закреплена справа; и остается фиксированной шириной / высотой (по правому краю).
- метка и нижнее изображение делят оставшееся левое пространство
- метка расположена вертикально по центру в верхней половине верхнего оставшегося пространства
- нижнее изображение остается в центре (как вертикально, так и горизонтально) в нижнем оставшемся пространстве
- если метка шире нижнего изображения, то вид должен расширяться
Я счастлив построить это в чистом коде, если требуется. Я использовал XIB на изображениях выше, чтобы играть с атрибутами и визуализировать мой вопрос.
Я из C#/XAML, поэтому я обычно использую сетку с фиксированными /auto/* столбцами и строками, но я предполагаю, что мне нужно использовать что-то вроде NSLayoutConstraints - к сожалению, я не знаю, с чего начать и как искать решение. Любая помощь приветствуется!
1 ответ
В вашем UIButton
(код не проверен)
//put the code below in your button's init method
UILabel *label = [[UILabel alloc] init];
UIImageView *bottomImageView = [[UIImageView alloc] init];
UIImageView *rightImageView = [[UIImageView alloc] init];
// we define our own contraints,
// we don't want the system to fall-back on UIView's autoresizingMask property (pre-iOS 6)
self.translatesAutoresizingMaskIntoConstraints = NO;
label.translatesAutoresizingMaskIntoConstraints = NO;
bottomImageView.translatesAutoresizingMaskIntoConstraints = NO;
rightImageView.translatesAutoresizingMaskIntoConstraints = NO;
//fixed sizes => SET THESE as you want
CGFloat labelHeight, bottomWidth, rightImageWidth;
// 1 - Label constraints :
// labelWidth = 1 *self.width - rightImageWidth
NSLayoutConstraint *labelWidth = [NSLayoutConstraint constraintWithItem:label
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:self
attribute:NSLayoutAttributeWidth
multiplier:1
constant:(- rightImageWidth)];
// label must be at the top :
NSLayoutConstraint *labelTop = [NSLayoutConstraint constraintWithItem:label
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self
attribute:NSLayoutAttributeTop
multiplier:1
constant:0];
//label must be on the left border
NSLayoutConstraint *labelLeft = [NSLayoutConstraint constraintWithItem:label
attribute:NSLayoutAttributeLeft
relatedBy:NSLayoutRelationEqual
toItem:self
attribute:NSLayoutAttributeLeft
multiplier:1
constant:0];
//label must be of 1/2 height
NSLayoutConstraint *labelHeight = [NSLayoutConstraint constraintWithItem:label
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:self
attribute:NSLayoutAttributeHeight
multiplier:0.5
constant:0];
[self addSubview:label];
[self addConstraints:@[labelWidth, labelTop, labelLeft, labelHeight]];
//2 - botom view
// width constant
NSLayoutContraint *bottomWidth = [NSLayoutConstraint constraintWithItem:bottomImageView
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:0
constant:bottomWidth];
// same height constraint as label
NSLayoutConstraint *bottomHeight = [NSLayoutConstraint constraintWithItem:bottomImageView
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:self
attribute:NSLayoutAttributeHeight
multiplier:0.5
constant:0];
// sticks at container's bottom (pun intended)
NSLayoutConstraint *bottomBottom = [NSLayoutConstraint constraintWithItem:bottomImageView
attribute:NSLayoutAttributeBottom
relatedBy:NSLayoutRelationEqual
toItem:self
attribute:NSLayoutAttributeBottom
multiplier:1
constant:0];
//we have height, width, y contraints, just x remains
// NOTE : this one is between bottom view and label
NSLayoutConstraint *bottomCenteredXAsLabel = [NSLayoutConstraint constraintWithItem:bottomImageView
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:label
attribute:NSLayoutAttributeCenterX
multiplier:1
constant:0];
[self addSubview:bottomImageView];
[self addConstraints:@[bottomWidth, bottomHeight, bottomBottom, bottomCenteredXAsLabel]];
// 3 - last one !
NSLayoutConstraint *rightAligned = [NSLayoutConstraint constraintWithItem:rightImageView
attribute:NSLayoutAttributeRight
relatedBy:NSLayoutRelationEqual
toItem:self
attribute:NSLayoutAttributeRight
multiplier:1
constant:0];
//right height
NSLayoutConstraint *rightHeight = [NSLayoutConstraint constraintWithItem:rightImageView
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:self
attribute:NSLayoutAttributeHeight
multiplier:1
constant:0];
//constant width...
NSLayoutConstraint *rightWidth = [NSLayoutConstraint constraintWithItem:rightImageView
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:0
constant:rightImageWidth];
//width, height, x constraints...
//we still need one on y, let's say it sticks at the top
NSLayoutConstraint *rightTop = [NSLayoutConstraint constraintWithItem:rightImageView
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self
attribute:NSLayoutAttributeTop
multiplier:1
constant:0];
[self addSubview:rightImageView];
[self addConstraints:@[rightAligned, rightHeight, rightWidth, rightTop]];
И вуаля!
Метод всегда один и тот же: вам нужно как минимум 4 ограничения для каждого вида, настройка ширины, высоты, x и y (размеры CGRect 4). Думайте об ограничении как об отношении:
item1.layoutAttribute1 >= a*item2.layoutAttribute2 + b
перевести в эту форму
[NSLayoutConstraint constraintWithItem:item1
attribute:layoutAttribute1
relatedBy:NSLayoutRelationGreaterThanOrEqual
toItem:item2
attribute:layoutAttribute2
multiplier:a
constant:b];
Обратите внимание, что используя визуальный формат, вы можете выразить все это с меньшим количеством кода. (но я еще не играл с этим).