Центрирование представления в своем супервизоре с использованием языка Visual Format
Я только начал изучать AutoLayout для iOS и посмотрел на язык Visual Format.
Все работает отлично, за исключением одного: я просто не могу получить представление, чтобы сосредоточиться в его супервизии.
Возможно ли это с помощью VFL или мне нужно вручную создать ограничение?
Ответы
Ответ 1
В настоящее время нет, это не похоже на то, что можно центрировать представление в супервизии, используя только VFL. Однако это не так сложно сделать, используя одну строку VFL и одно дополнительное ограничение (на ось):
VFL: "|-(>=20)-[view]-(>=20)-|"
[NSLayoutConstraint constraintWithItem:view
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:view.superview
attribute:NSLayoutAttributeCenterX
multiplier:1.f constant:0.f];
Можно подумать, что вы просто сможете это сделать (это то, что я изначально думал и пытался, когда увидел этот вопрос):
[NSLayoutConstraint constraintsWithVisualFormat:@"|-(>=20)-[view(==200)]-(>=20)-|"
options: NSLayoutFormatAlignAllCenterX | NSLayoutFormatAlignAllCenterY
metrics:nil
views:@{@"view" : view}];
Я попробовал много разных вариантов выше, пытаясь согнуть его по своей воле, но это, похоже, не относится к супервизу, даже когда явно имеет две отдельные строки VFL для обеих осей (H:|V:
). Затем я начал пытаться изолировать, когда параметры применяются к VFL. Они, похоже, не применяются к супервину в VFL и будут применяться только к любым явным представлениям, которые упоминаются в строке VFL (что в некоторых случаях неутешительно).
Я надеюсь, что в будущем Apple добавит какой-то новый вариант, чтобы опции VFL учитывали супервизор, даже если это делается только тогда, когда есть только один явный вид, кроме супервизора в VFL. Другим решением может быть другой вариант, переданный в VFL, который говорит что-то вроде: NSLayoutFormatOptionIncludeSuperview
.
Излишне говорить, что я много узнал о том, как VFL пытается ответить на этот вопрос.
Ответ 2
Да, можно сосредоточить представление в своем супервизоре с помощью языка Visual Format. Вертикально и горизонтально. Вот демо:
https://github.com/evgenyneu/center-vfl
Ответ 3
Я думаю, что лучше вручную создавать ограничения.
[superview addConstraint:
[NSLayoutConstraint constraintWithItem:view
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:superview
attribute:NSLayoutAttributeCenterX
multiplier:1
constant:0]];
[superview addConstraint:
[NSLayoutConstraint constraintWithItem:view
attribute:NSLayoutAttributeCenterY
relatedBy:NSLayoutRelationEqual
toItem:superview
attribute:NSLayoutAttributeCenterY
multiplier:1
constant:0]];
Теперь мы можем использовать NSLayoutAnchor для программного определения AutoLayout:
(Доступно в iOS 9.0 и новее)
view.centerXAnchor.constraint(equalTo: superview.centerXAnchor).isActive = true
view.centerYAnchor.constraint(equalTo: superview.centerYAnchor).isActive = true
Я рекомендую использовать SnapKit, который является DSL, чтобы упростить автоматическую компоновку как на iOS, так и на macOS.
view.snp.makeConstraints({ $0.center.equalToSuperview() })
Ответ 4
Абсолютно возможно удалось сделать это вот так:
[NSLayoutConstraint constraintsWithVisualFormat:@"H:[view]-(<=1)-[subview]"
options:NSLayoutFormatAlignAllCenterY
metrics:nil
views:NSDictionaryOfVariableBindings(view, subview)];
Узнал это из здесь.
Код над центрами, по мнению Y, очевидно.
Swift3:
NSLayoutConstraint.constraints(withVisualFormat: "H:[view]-(<=1)-[subview]",
options: .alignAllCenterY,
metrics: nil,
views: ["view":self, "subview":_spinnerView])
Ответ 5
Добавьте код ниже и нажмите кнопку в центре экрана. Абсолютно возможно.
[self.view addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat:@"H:|-[button]-|"
options:NSLayoutFormatAlignAllCenterY
metrics:0
views:views]];
[self.view addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat:@"V:|-[button]-|"
options:NSLayoutFormatAlignAllCenterX
metrics:0
views:views]];
Ответ 6
Я знаю, что вы этого не хотите, но вы можете, конечно, рассчитать поля и использовать их для создания строки визуального формата;)
В любом случае, нет. К сожалению, это невозможно сделать "автоматически" с VFL - по крайней мере, пока.
Ответ 7
Благодаря ответу от @Evgenii, я создаю полный пример в gist:
центрировать красный квадрат по вертикали с пользовательской высотой
https://gist.github.com/yallenh/9fc2104b719742ae51384ed95dcaf626
Вы можете центрировать представление по вертикали, используя VFL (который не совсем интуитивно понятен) или используйте ограничения вручную.
Кстати, я не могу совмещать как центр Y, так и высоту вместе в VFL, например:
"H:[subView]-(<=1)-[followIcon(==customHeight)]"
В текущем решении ограничения VFL добавляются отдельно.
Ответ 8
Что нужно сделать, так это то, что супервизор должен быть объявлен в словаре. Вместо использования |
вы используете @{@"super": view.superview};
.
И NSLayoutFormatAlignAllCenterX
для вертикального и NSLayoutFormatAlignAllCenterY
для горизонтальных в качестве параметров.
Ответ 9
Вы можете использовать дополнительные виды.
NSDictionary *formats =
@{
@"H:|[centerXView]|": @0,
@"V:|[centerYView]|": @0,
@"H:[centerYView(0)]-(>=0)-[yourView]": @(NSLayoutFormatAlignAllCenterY),
@"V:[centerXView(0)]-(>=0)-[yourView]": @(NSLayoutFormatAlignAllCenterX),
};
NSDictionary *views = @{
@"centerXView": centerXView,
@"centerYView": centerYView,
@"yourView": yourView,
};
^(NSString *format, NSNumber *options, BOOL *stop) {
[superview addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:format
options:options.integerValue
metrics:nil
views:views]];
}];
Если вы хотите, чтобы он был аккуратным, тогда centerXView.hidden = centerYView.hidden = YES;
.
PS: Я не уверен, что могу назвать дополнительные представления "заполнителями", потому что английский - это мой второй язык. Будет оценено, если кто-то скажет мне это.
Ответ 10
Для тех, кто пришел сюда для решения Interface Builder
(Google приводит меня сюда), просто добавьте ограничения ширины/высоты const и выберите subview → control drag to this superview → выберите "center vertical/horizontally in SuperView".
Ответ 11
@igor-muzyka ответ в Swift:
NSLayoutConstraint.constraintsWithVisualFormat("H:[view]-(<=1)-[subview]",
options: .AlignAllCenterY,
metrics: nil,
views: ["view":view, "subview":subview])
Ответ 12
Просто нужно сказать, что u может использовать это вместо ограничений:
child.center = [parent convertPoint:parent.center fromView:parent.superview];
Ответ 13
Вместо использования VFL вы можете легко сделать это в построителе интерфейса. В Главной раскадровке нажмите Ctrl + клик по виду, которое хотите центрировать. Перетащите в супервизор (удерживая Ctrl) и выберите "Центр X" или "Центр Y". Не требуется код.