Я пытаюсь использовать новые авто Layout в Льва, потому что это кажется довольно хорошим. Но я не могу найти хорошую информацию о том, как сделать вещи. Например:
У меня есть две метки:
+----------------+
| +------------+ |
| + label 1 | |
| +------------+ |
| |
| +------------+ |
| | label 2 | |
| +------------+ |
+----------------+
но первая этикетка не всегда наполняются содержанием, иногда там исть просто нет контента для него. Что я хочу сделать, это автоматически покажите этикетку 2, где цифра 1 будет, когда он будет иметь содержание.
+----------------+
| +------------+ |
| + label 2 | |
| +------------+ |
| |
| |
| |
| |
+----------------+
Какие ограничения я должен добавить, так это работает автоматически с Autolayout? Я понимаю, что я мог бы просто код и все, но у меня около 30 таких надписей и изображений и кнопок разных стилей и форм, которые являются необязательными, и я Дон'т хотите добавить hundrets строк кода, когда он может работать автоматически тоже довольно неплохо.
Если это не сработает, то я буду просто использовать WebView и сделать это с HTML и CSS.
Это возможно с авто макет, но не'т точно хорошо масштабируется.
Поэтому, принимая ваш пример, пусть'ы сказать, у вас есть метка, и метка Б (или кнопку или что-нибудь еще действительно). Сначала начните с добавления верхнее ограничение на суперпанель для А. затем вертикальные ограничения расстояния между A и B. Это все нормально до сих пор. Если вы должны были снять в этот момент, Б неоднозначный макет. Если вы были, чтобы скрыть его, оно все равно занимает это'ы пространства, включая пространства между метками.
Далее нужно добавить еще одно ограничение, с Б, в верхней части суперпанель. Изменить приоритет на этом будет ниже, чем в других (скажем 900), а затем установить его's фиксировано, чтобы быть стандартными (или другое меньшее значение). Теперь, когда удаляется от него'ы суперпанель, низкий приоритет ограничение будет пипец и тяги Б к верху. Ограничения выглядят примерно так:
Проблема приходит, когда вы пытаетесь сделать это с длинным списком меток.
Одним простым решением является просто подкласс UILabel ни и менять внутренний размер содержимого.
@implementation WBSCollapsingLabel
- (CGSize)intrinsicContentSize
{
if (self.isHidden) {
return CGSizeMake(UIViewNoIntrinsicMetric, 0.0f);
} else {
return [super intrinsicContentSize];
}
}
- (void)setHidden:(BOOL)hidden
{
[super setHidden:hidden];
[self updateConstraintsIfNeeded];
[self layoutIfNeeded];
}
@end
Эта категория делает рушится макет авто ограничен вид очень простой:
https://github.com/depth42/AutolayoutExtensions
Я просто добавил его в проект и он отлично работает.
Я не'т думаю, что вы могли бы сделать это таким образом. Если вы сделали макет для этикетки 2 быть в зависимости от расстояния ограничение от метку 1, даже если вы сделали ярлык 1 авто-обвал до нуля высоты, когда она не имеет содержания, ярлык 2 по-прежнему будет то расстояние вниз, т. е. в:
+----------------+
| +------------+ |
| + label 1 | |
| +------------+ |
| ^ |
| ^ !
| +------------+ |
| | label 2 | |
| +------------+ |
+----------------+
Где ^ - это режим ограничений расстояния - если метки 1 и знает, как стать нулевой высотой, когда она's строка пуста, вы'вновь все собираюсь:
+----------------+
| +------------+ |
| ^ |
| ^ !
| +------------+ |
| | label 2 | |
| +------------+ |
+----------------+
Может можно создать свой NSLayoutConstraint вручную. Вы могли бы сделать второй атрибут-высота метку 1, Сделайте постоянный ноль, а потом тщательно разобраться, что множитель будет сделать так, чтобы расстояние быть то, что вы хотите на основе нескольких ненулевых высота ярлыка.
Но проделав все это, вы'вэ теперь закодированы в NSLabel подкласс, который авто-размеры, создан объект ограничение вручную, а не через визуальный язык, и наклонился NSLayoutConstraint помимо его воли.
Я думаю, что вы'вновь лучше просто сменить рамки ярлыка 2 если метки 1's строка пустая!
Здесь'ы пример того, как я справился с это программно, а не с помощью построителя интерфейса. В резюме, я только добавить мнение, если это'с поддержкой, а затем перебрать подпанелей, добавив вертикальные ограничения, как я иду.
Обратите внимание, что взгляды на вопрос инициализируются до этого.
/*
Begin Auto Layout
*/
NSMutableArray *constraints = [NSMutableArray array];
NSMutableDictionary *views = [[NSMutableDictionary alloc] init];
/*
Label One
*/
if (enableLabelOne) {
[contentView addSubview:self.labelOne];
self.labelOne.translatesAutoresizingMaskIntoConstraints = NO;
[views setObject:self.labelOne
forKey:@"_labelOne"];
[constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[_labelOne(44)]"
options:0
metrics:nil
views:views]];
[constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[_labelOne]-|"
options:0
metrics:nil
views:views]];
}
/*
Label Two
*/
if (enableLabelTwo) {
[contentView addSubview:self.labelTwo];
self.labelTwo.translatesAutoresizingMaskIntoConstraints = NO;
[views setObject:self.labelTwo
forKey:@"_labelTwo"];
[constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[_labelTwo(44)]"
options:0
metrics:nil
views:views]];
}
[constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[_labelTwo]-|"
options:0
metrics:nil
views:views]];
/*
Dynamically add vertical spacing constraints to subviews
*/
NSArray *subviews = [contentView subviews];
if ([subviews count] > 0) {
UIView *firstView = [subviews objectAtIndex:0];
UIView *secondView = nil;
UIView *lastView = [subviews lastObject];
[constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[firstView]"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(firstView)]];
for (int i = 1; i < [subviews count]; i++) {
secondView = [subviews objectAtIndex:i];
[constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[firstView]-10-[secondView]"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(firstView, secondView)]];
firstView = secondView;
}
[constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[lastView]-|"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(lastView)]];
}
[self addConstraints:constraints];
Я'м задание lastView
ограничение, так как этот код был адаптирован от чего-то внутри UIScrollView.
Изначально я реализовал это на основе этот переполнение стека ответ и изменил все под мои потребности.
Я нашел seemlingly достойный способ сделать это. Это'ы, похожие на Дэвид'с. Здесь's, как это работает в коде. Я создал суперпанель и все это'ы подпанелей, даже те, которые не всегда показаны. Я добавил много ограничений, например, в:|-[_btn] к суперпанель. Как вы можете видеть в конце этих ограничений нет по ссылке внизу на суперпанель. Затем я создал два массива ограничений для обоих государств считает, для меня разница-это 'больше возможностей' треугольник. Тогда, когда треугольник нажал в зависимости от его's в состоянии добавить и удалить соответственно ограничений и подпанелей. Например, чтобы добавить я:
[self.backgroundView removeConstraints:self.lessOptionsConstraints];
[self.backgroundView addSubview:self.nameField];
[self.backgroundView addConstraints:self.moreOptionsConstraints];
Ограничения я снял привязал кнопку в нижней части суперпанель как в:[_btn]-|. Ограничения я добавила выглядеть в:[_btn]-[_nameField]-|
как вы можете видеть это ограничение места в между оригинальным видом над ней и нижней части суперпанель, который расширяет суперпанель'с высоты.
Я'вэ нашел другой способ сделать это. Эта методика может применяться в любом месте, нет проблем масштабирования; и обрабатывает поля, а также. И вы Don'т нужно 3 штуки для него.
Во-первых, не используйте этот макет:
V:|-?-[Label1]-10-[Label2]-10-|
H:|-?-[Label1]-?-|
H:|-20-[Label2]-20-|
Вместо того, чтобы использовать эти:
("|" is the real (outer) container)
V:|-?-[Label1]-0-[Label2HideableMarginContainer]-0-|
H:|-?-[Label1]-?-|
H:|-0-[Label2HideableMarginContainer]-0-|
("|" is Label2HideableMarginContainer)
V:|-10-[Label2]-10-|
H:|-20-[Label2]-20-|
Так что мы сделали сейчас? Метка2
непосредственно не используемые в макете; его'ы, помещенные в поле-контейнер. Этот контейнер используется в качестве **прокси-сервер** в
Метка2, **с 0 полей в макете. Реальная маржа положить внутрь** в поле-контейнер
.
Теперь мы можем скрыть Метка2
с:
скрытые
на да
на немИ
верх
, низ
, ведущий
и трала
ограничений. Так что искать их, чем набор "активный "" нет " на них. Это приведет к маржа-контейнер
иметь размер кадра
из (0,0); потому что у него есть подпанели(ы); но разве'т любой (активный) макет ограничений, которая закрепляет эти подпанелей к нему.Может быть немного сложным, но вы должны только после ее развивать. Всю логику можно поместить в отдельное место, и использовать повторно каждый раз, когда вам нужно скрыть СМГ.
Вот код C# в Xamarin как искать тех ограничений, которая закрепляет на подпанели(ы) на внутренние края маржа-контейнер вид
:
public List<NSLayoutConstraint> SubConstraints { get; private set; }
private void ReadSubContraints()
{
var constraints = View.Constraints; // View: the Margin-Container NSView
if(constraints?.Any() ?? false)
{
SubConstraints = constraints.Where((NSLayoutConstraint c) => {
var predicate =
c.FirstAttribute == NSLayoutAttribute.Top ||
c.FirstAttribute == NSLayoutAttribute.Bottom ||
c.FirstAttribute == NSLayoutAttribute.Leading ||
c.FirstAttribute == NSLayoutAttribute.Trailing;
predicate &= ViewAndSubviews.Contains(c.FirstItem); // ViewAndSubviews: The View and View.Subviews
predicate &= ViewAndSubviews.Contains(c.SecondItem);
return predicate;
}).ToList();
}
}
Решить эту проблему программно. У меня есть несколько кнопок в ряд, и я решил спрятаться в любой момент.
Используется картографии, чтобы заменить их каждый раз, когда "скрытые" изменения в любой из них.
let buttons = self.buttons!.filter { button in
return !button.hidden
}
constrain(buttons, replace: self.constraintGroup) { buttons in
let superview = buttons.first!.superview!
buttons.first!.left == superview.left
for var i = 1; i < buttons.count; i++ {
buttons[i].left == buttons[i-1].right + 10
}
buttons.last!.right == superview.right
}