Не существует «встроенного» способа центрировать вид с помощью языка визуальных форматов.Вы можете найти попытки, которые могут показаться работающими, но могут быть ненадежными и могут потерпеть неудачу, если iOS что-то изменит.
Вы можете получить желаемый макет, используя пару «проставочных» представлений:
view.addConstraints(NSLayoutConstraint.constraints(
withVisualFormat: "H:|-8-[btn1(btn3)][spacer1(spacer2)][btn2(btn3)][spacer2][btn3]-8-|",
options: [.alignAllCenterY],
metrics: nil,
views: views))
Примечание: гораздо проще отслеживать вещи, используя словарь фактических представлений, а не «помощник», который дает вам v1, v2, v3 и т. Д. *
Результат:
Итак, |-8-
и -8-|
означают 8-pts from the edge
, поэтому у вас есть небольшие отступы слева и справа. *Для 1020 *
btn1
и btn2
установлено равное значение ширины btn3
, поэтому все 3 кнопки имеют одинаковую ширину.
spacer1
установлено равное значение ширины spacer2
, поэтому обе распоркисохраняйте одинаковую ширину.
Заданные фоновые изображения заданы на .clear
... но, поскольку мы не дали им ограничение высоты, они будут иметь высоту ноль и не будут видны в любом случае.
Вот код, который я использовал - вы можете запустить его непосредственно на странице игровой площадки или использовать его в качестве контроллера вида:
import UIKit
import PlaygroundSupport
class MyViewController : UIViewController {
var commentButton: UIButton = {
let b = UIButton()
b.setTitle("Comment", for: .normal)
b.backgroundColor = .red
return b
}()
var likeButton: UIButton = {
let b = UIButton()
b.setTitle("Like", for: .normal)
b.backgroundColor = .red
return b
}()
var mapButton: UIButton = {
let b = UIButton()
b.setTitle("Map", for: .normal)
b.backgroundColor = .red
return b
}()
var spacer1: UIView = {
let v = UIView()
v.backgroundColor = .yellow
return v
}()
var spacer2: UIView = {
let v = UIView()
v.backgroundColor = .yellow
return v
}()
override func viewDidLoad() {
view.backgroundColor = .white
view.addSubview(commentButton)
view.addSubview(likeButton)
view.addSubview(mapButton)
view.addSubview(spacer1)
view.addSubview(spacer2)
let views = [
"btn1" : commentButton,
"btn2" : likeButton,
"btn3" : mapButton,
"spacer1" : spacer1,
"spacer2" : spacer2,
]
views.forEach {
$0.value.translatesAutoresizingMaskIntoConstraints = false
}
view.addConstraints(NSLayoutConstraint.constraints(
withVisualFormat: "V:|-8-[btn1]",
options: [],
metrics: nil,
views: views))
view.addConstraints(NSLayoutConstraint.constraints(
withVisualFormat: "H:|-8-[btn1(btn3)][spacer1(spacer2)][btn2(btn3)][spacer2][btn3]-8-|",
options: [.alignAllCenterY],
metrics: nil,
views: views))
}
}
PlaygroundPage.current.liveView = MyViewController()
Редактировать:
Кстати, гораздо проще использовать NSLayoutConstraint
, чем VFL
- более гибко.И, это не нуждается в представлениях "распорки".
Вот пример.Он создает ту же схему, что и выше (опять же, может быть запущен на странице игровой площадки или в качестве источника контроллера представления):
import UIKit
import PlaygroundSupport
class MyViewController : UIViewController {
var commentButton: UIButton = {
let b = UIButton()
b.setTitle("Comment", for: .normal)
b.backgroundColor = .red
return b
}()
var likeButton: UIButton = {
let b = UIButton()
b.setTitle("Like", for: .normal)
b.backgroundColor = .red
return b
}()
var mapButton: UIButton = {
let b = UIButton()
b.setTitle("Map", for: .normal)
b.backgroundColor = .red
return b
}()
override func viewDidLoad() {
view.backgroundColor = .white
view.addSubview(commentButton)
view.addSubview(likeButton)
view.addSubview(mapButton)
[commentButton, likeButton, mapButton].forEach {
$0.translatesAutoresizingMaskIntoConstraints = false
}
NSLayoutConstraint.activate([
// commentButton 8-pts from top, 8-pts from left
commentButton.topAnchor.constraint(equalTo: view.topAnchor, constant: 8.0),
commentButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 8.0),
// likeButton 8-pts from top, centered horizontally
likeButton.topAnchor.constraint(equalTo: view.topAnchor, constant: 8.0),
likeButton.centerXAnchor.constraint(equalTo: view.centerXAnchor, constant: 0.0),
// mapButton 8-pts from top, 8-pts from right
mapButton.topAnchor.constraint(equalTo: view.topAnchor, constant: 8.0),
mapButton.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -8.0),
// commentButton and likeButton widths equal to mapButton width
commentButton.widthAnchor.constraint(equalTo: mapButton.widthAnchor),
likeButton.widthAnchor.constraint(equalTo: mapButton.widthAnchor),
])
}
}
PlaygroundPage.current.liveView = MyViewController()