以编程方式使用自动布局的最佳实践
Best Practices for programmatically using autolayout
我在我的整个应用程序中以编程方式使用 auto layout
,但我真的很难让我的应用程序在所有设备上看起来都不错(尤其是在 iPhone SE 上)。这是我的 StartViewController
(SE、8 和 11 Pro Max)的示例:
如您所见,iPhone 8 和 11 Pro Max 上的视图看起来相当不错。但是在 iPhone SE 上它很糟糕。我不太明白为什么,因为 space 可以像 iPhone 8 那样布置所有视图?出于某种原因,我认为 buttons
和 labels
更大(可能只是一种错觉)。
我的问题是如何解决这个问题?什么是最佳实践?缩小 fontSize
?使 buttons
更小?获得适用于每个 iPhone 的动态布局的最佳方法是什么?显然我没有以最好的方式使用自动布局...
下面是我如何限制图片中的 views
:
//MARK: setupViews
func setUpViews(){
view.addSubview(backgroundImage)
view.addSubview(willkommenLabel)
view.addSubview(textLabel)
view.addSubview(emailButton)
emailButton.addSubview(emailImage)
view.addSubview(oderLabel)
view.addSubview(lineLeft)
view.addSubview(lineRight)
view.addSubview(facebookButton)
facebookButton.addSubview(facebookLogo)
view.addSubview(googleButton)
googleButton.addSubview(googleLogo)
view.addSubview(appleButton)
appleButton.addSubview(appleLogo)
view.addSubview(documentsLabel)
backgroundImage.topAnchor.constraint(equalTo: view.topAnchor, constant: -20).isActive = true
backgroundImage.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 20).isActive = true
backgroundImage.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: -20).isActive = true
backgroundImage.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 20).isActive = true
willkommenLabel.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 80).isActive = true
willkommenLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 30).isActive = true
willkommenLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -30).isActive = true
textLabel.topAnchor.constraint(equalTo: willkommenLabel.bottomAnchor, constant: 30).isActive = true
textLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 30).isActive = true
textLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -30).isActive = true
emailButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 30).isActive = true
emailButton.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -30).isActive = true
emailButton.topAnchor.constraint(equalTo: textLabel.topAnchor, constant: 100).isActive = true
emailButton.heightAnchor.constraint(equalToConstant: 50).isActive = true
emailImage.centerYAnchor.constraint(equalTo: emailButton.centerYAnchor).isActive = true
emailImage.leadingAnchor.constraint(equalTo: emailButton.leadingAnchor, constant: 10).isActive = true
emailImage.heightAnchor.constraint(equalToConstant: 25).isActive = true
emailImage.widthAnchor.constraint(equalToConstant: 25).isActive = true
oderLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
oderLabel.bottomAnchor.constraint(equalTo: emailButton.bottomAnchor, constant: 40).isActive = true
oderLabel.widthAnchor.constraint(equalToConstant: 60).isActive = true
lineLeft.centerYAnchor.constraint(equalTo: oderLabel.centerYAnchor).isActive = true
lineLeft.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 30).isActive = true
lineLeft.trailingAnchor.constraint(equalTo: oderLabel.leadingAnchor).isActive = true
lineRight.centerYAnchor.constraint(equalTo: oderLabel.centerYAnchor).isActive = true
lineRight.leadingAnchor.constraint(equalTo: oderLabel.trailingAnchor).isActive = true
lineRight.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -30).isActive = true
facebookButton.leadingAnchor.constraint(equalTo: emailButton.leadingAnchor).isActive = true
facebookButton.trailingAnchor.constraint(equalTo: emailButton.trailingAnchor).isActive = true
facebookButton.bottomAnchor.constraint(equalTo: oderLabel.bottomAnchor, constant: 55 + 10).isActive = true
facebookButton.heightAnchor.constraint(equalToConstant: 50).isActive = true
facebookLogo.centerYAnchor.constraint(equalTo: facebookButton.centerYAnchor).isActive = true
facebookLogo.leadingAnchor.constraint(equalTo: facebookButton.leadingAnchor, constant: 10).isActive = true
facebookLogo.heightAnchor.constraint(equalToConstant: 25).isActive = true
facebookLogo.widthAnchor.constraint(equalToConstant: 25).isActive = true
googleButton.leadingAnchor.constraint(equalTo: emailButton.leadingAnchor).isActive = true
googleButton.trailingAnchor.constraint(equalTo: emailButton.trailingAnchor).isActive = true
googleButton.bottomAnchor.constraint(equalTo: facebookButton.bottomAnchor, constant: 55 + 10).isActive = true
googleButton.heightAnchor.constraint(equalToConstant: 50).isActive = true
googleLogo.centerYAnchor.constraint(equalTo: googleButton.centerYAnchor).isActive = true
googleLogo.leadingAnchor.constraint(equalTo: googleButton.leadingAnchor, constant: 10).isActive = true
googleLogo.heightAnchor.constraint(equalToConstant: 25).isActive = true
googleLogo.widthAnchor.constraint(equalToConstant: 25).isActive = true
appleButton.leadingAnchor.constraint(equalTo: emailButton.leadingAnchor).isActive = true
appleButton.trailingAnchor.constraint(equalTo: emailButton.trailingAnchor).isActive = true
appleButton.bottomAnchor.constraint(equalTo: googleButton.bottomAnchor, constant: 55 + 10).isActive = true
appleButton.heightAnchor.constraint(equalToConstant: 50).isActive = true
appleLogo.centerYAnchor.constraint(equalTo: appleButton.centerYAnchor).isActive = true
appleLogo.leadingAnchor.constraint(equalTo: appleButton.leadingAnchor, constant: 10).isActive = true
appleLogo.heightAnchor.constraint(equalToConstant: 25).isActive = true
appleLogo.widthAnchor.constraint(equalToConstant: 25).isActive = true
documentsLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 10).isActive = true
documentsLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -10).isActive = true
documentsLabel.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -5).isActive = true
}
实际上这取决于您希望布局在每个设备中的显示方式,因此如果您希望所有元素的高度固定,那么您应该将所有元素包装在一个滚动视图中,该滚动视图将为小型设备滚动并在不存在时执行大型设备,或者如果您需要使元素适合所有设备的屏幕,那么您应该使高度限制与屏幕高度成比例
试试这个。
它使用了几个百分比的高度(基于您在 iPhone 8 屏幕上的原始布局)。
我没有更改您现有的任何代码。只需添加以下 func
并将您的呼叫从:
setupViews()
到
setupViewsDon()
应该从评论中清楚地知道您可能想要进行任何调整...但希望这会让您接近您的目标 - 也许您会发现一些提示以供将来使用:
func setupViewsDon(){
// setting these properties here, so I don't have to change your original initialization
willkommenLabel.numberOfLines = 1
willkommenLabel.adjustsFontSizeToFitWidth = true
willkommenLabel.minimumScaleFactor = 0.5
textLabel.numberOfLines = 2
textLabel.adjustsFontSizeToFitWidth = true
textLabel.minimumScaleFactor = 0.5
// prevent willkommenLabel from being compressed or streched
willkommenLabel.setContentHuggingPriority(.required, for: .vertical)
willkommenLabel.setContentCompressionResistancePriority(.required, for: .vertical)
// prevent oderLabel from being compressed or streched
oderLabel.setContentHuggingPriority(.required, for: .vertical)
oderLabel.setContentCompressionResistancePriority(.required, for: .vertical)
// prevent documentsLabel from being compressed or streched
documentsLabel.setContentHuggingPriority(.required, for: .vertical)
documentsLabel.setContentCompressionResistancePriority(.required, for: .vertical)
view.addSubview(backgroundImage)
view.addSubview(willkommenLabel)
view.addSubview(textLabel)
view.addSubview(emailButton)
emailButton.addSubview(emailImage)
view.addSubview(oderLabel)
view.addSubview(lineLeft)
view.addSubview(lineRight)
view.addSubview(facebookButton)
facebookButton.addSubview(facebookLogo)
view.addSubview(googleButton)
googleButton.addSubview(googleLogo)
view.addSubview(appleButton)
appleButton.addSubview(appleLogo)
view.addSubview(documentsLabel)
backgroundImage.topAnchor.constraint(equalTo: view.topAnchor, constant: -20).isActive = true
backgroundImage.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 20).isActive = true
backgroundImage.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: -20).isActive = true
backgroundImage.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 20).isActive = true
// add a layout guide for percentage top spacing
let topSpaceGuide = UILayoutGuide()
view.addLayoutGuide(topSpaceGuide)
// based on iPhone 8 ... 80-pts from top
// will be shorter on smaller devices, taller on larger devices
topSpaceGuide.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
topSpaceGuide.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 80.0 / 667.0).isActive = true
willkommenLabel.topAnchor.constraint(equalTo: topSpaceGuide.bottomAnchor).isActive = true
willkommenLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 30).isActive = true
willkommenLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -30).isActive = true
// textLabel top constrained to willkommenLabel bottom
textLabel.topAnchor.constraint(equalTo: willkommenLabel.bottomAnchor, constant: 0).isActive = true
textLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 30).isActive = true
textLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -30).isActive = true
// textLabel height = a percentage of view height using 100-pts based on an iPhone 8
// priority = .defaultHigh so it can be compressed if needed (on smaller devices)
let c = textLabel.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 100.0 / 667.0)
c.priority = .defaultHigh
c.isActive = true
// set email button height
emailButton.heightAnchor.constraint(equalToConstant: 50).isActive = true
// set other button heights equal to emailButton
facebookButton.heightAnchor.constraint(equalTo: emailButton.heightAnchor).isActive = true
googleButton.heightAnchor.constraint(equalTo: emailButton.heightAnchor).isActive = true
appleButton.heightAnchor.constraint(equalTo: emailButton.heightAnchor).isActive = true
// add the logo images to the buttons, and make their heights relative to button heights
// in case you want to change the button heights
for (btn, img) in [(emailButton, emailImage), (facebookButton, facebookLogo), (googleButton, googleLogo), (appleButton, appleLogo)] {
btn.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 30).isActive = true
btn.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -30).isActive = true
btn.addSubview(img)
img.centerYAnchor.constraint(equalTo: btn.centerYAnchor).isActive = true
img.leadingAnchor.constraint(equalTo: btn.leadingAnchor, constant: 10).isActive = true
img.heightAnchor.constraint(equalTo: btn.heightAnchor, multiplier: 0.5).isActive = true
img.widthAnchor.constraint(equalTo: img.heightAnchor).isActive = true
}
emailButton.topAnchor.constraint(equalTo: textLabel.bottomAnchor, constant: 20).isActive = true
oderLabel.topAnchor.constraint(equalTo: emailButton.bottomAnchor, constant: 15).isActive = true
facebookButton.topAnchor.constraint(equalTo: oderLabel.bottomAnchor, constant: 15).isActive = true
googleButton.topAnchor.constraint(equalTo: facebookButton.bottomAnchor, constant: 10).isActive = true
appleButton.topAnchor.constraint(equalTo: googleButton.bottomAnchor, constant: 10).isActive = true
// make sure appleButton stays above documentsLabel
appleButton.bottomAnchor.constraint(lessThanOrEqualTo: documentsLabel.topAnchor, constant: -20.0).isActive = true
// horizontal arrangement of oderLabel and left/right lines
oderLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
oderLabel.widthAnchor.constraint(equalToConstant: 60).isActive = true
lineLeft.centerYAnchor.constraint(equalTo: oderLabel.centerYAnchor).isActive = true
lineLeft.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 30).isActive = true
lineLeft.trailingAnchor.constraint(equalTo: oderLabel.leadingAnchor).isActive = true
lineRight.centerYAnchor.constraint(equalTo: oderLabel.centerYAnchor).isActive = true
lineRight.leadingAnchor.constraint(equalTo: oderLabel.trailingAnchor).isActive = true
lineRight.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -30).isActive = true
// documentsLabel stay at bottom
documentsLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 10).isActive = true
documentsLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -10).isActive = true
documentsLabel.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -5).isActive = true
}
如果您希望您的设计在所有设备上都能完美运行,那么您必须尽可能避免设置常量值,除非有必要,这里您设置高度和填充固定数字,尝试将它们设置为与屏幕相关大小,例如,您可以在此处设置视图中的所有按钮并将其高度设置为屏幕的一半:
Let height = view.frame.size.height / 2
buttonView.heightAnchor.constrains(equalTo: height).isActive = true
并且还将按钮插入到 stackView 中,覆盖按钮视图并将其设置为均匀填充按钮。因此,您将平等地拥有所有按钮而不是硬编码,以及与运行该应用程序的任何设备的屏幕尺寸相关的按钮动态视图
我在我的整个应用程序中以编程方式使用 auto layout
,但我真的很难让我的应用程序在所有设备上看起来都不错(尤其是在 iPhone SE 上)。这是我的 StartViewController
(SE、8 和 11 Pro Max)的示例:
如您所见,iPhone 8 和 11 Pro Max 上的视图看起来相当不错。但是在 iPhone SE 上它很糟糕。我不太明白为什么,因为 space 可以像 iPhone 8 那样布置所有视图?出于某种原因,我认为 buttons
和 labels
更大(可能只是一种错觉)。
我的问题是如何解决这个问题?什么是最佳实践?缩小 fontSize
?使 buttons
更小?获得适用于每个 iPhone 的动态布局的最佳方法是什么?显然我没有以最好的方式使用自动布局...
下面是我如何限制图片中的 views
:
//MARK: setupViews
func setUpViews(){
view.addSubview(backgroundImage)
view.addSubview(willkommenLabel)
view.addSubview(textLabel)
view.addSubview(emailButton)
emailButton.addSubview(emailImage)
view.addSubview(oderLabel)
view.addSubview(lineLeft)
view.addSubview(lineRight)
view.addSubview(facebookButton)
facebookButton.addSubview(facebookLogo)
view.addSubview(googleButton)
googleButton.addSubview(googleLogo)
view.addSubview(appleButton)
appleButton.addSubview(appleLogo)
view.addSubview(documentsLabel)
backgroundImage.topAnchor.constraint(equalTo: view.topAnchor, constant: -20).isActive = true
backgroundImage.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 20).isActive = true
backgroundImage.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: -20).isActive = true
backgroundImage.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 20).isActive = true
willkommenLabel.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 80).isActive = true
willkommenLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 30).isActive = true
willkommenLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -30).isActive = true
textLabel.topAnchor.constraint(equalTo: willkommenLabel.bottomAnchor, constant: 30).isActive = true
textLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 30).isActive = true
textLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -30).isActive = true
emailButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 30).isActive = true
emailButton.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -30).isActive = true
emailButton.topAnchor.constraint(equalTo: textLabel.topAnchor, constant: 100).isActive = true
emailButton.heightAnchor.constraint(equalToConstant: 50).isActive = true
emailImage.centerYAnchor.constraint(equalTo: emailButton.centerYAnchor).isActive = true
emailImage.leadingAnchor.constraint(equalTo: emailButton.leadingAnchor, constant: 10).isActive = true
emailImage.heightAnchor.constraint(equalToConstant: 25).isActive = true
emailImage.widthAnchor.constraint(equalToConstant: 25).isActive = true
oderLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
oderLabel.bottomAnchor.constraint(equalTo: emailButton.bottomAnchor, constant: 40).isActive = true
oderLabel.widthAnchor.constraint(equalToConstant: 60).isActive = true
lineLeft.centerYAnchor.constraint(equalTo: oderLabel.centerYAnchor).isActive = true
lineLeft.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 30).isActive = true
lineLeft.trailingAnchor.constraint(equalTo: oderLabel.leadingAnchor).isActive = true
lineRight.centerYAnchor.constraint(equalTo: oderLabel.centerYAnchor).isActive = true
lineRight.leadingAnchor.constraint(equalTo: oderLabel.trailingAnchor).isActive = true
lineRight.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -30).isActive = true
facebookButton.leadingAnchor.constraint(equalTo: emailButton.leadingAnchor).isActive = true
facebookButton.trailingAnchor.constraint(equalTo: emailButton.trailingAnchor).isActive = true
facebookButton.bottomAnchor.constraint(equalTo: oderLabel.bottomAnchor, constant: 55 + 10).isActive = true
facebookButton.heightAnchor.constraint(equalToConstant: 50).isActive = true
facebookLogo.centerYAnchor.constraint(equalTo: facebookButton.centerYAnchor).isActive = true
facebookLogo.leadingAnchor.constraint(equalTo: facebookButton.leadingAnchor, constant: 10).isActive = true
facebookLogo.heightAnchor.constraint(equalToConstant: 25).isActive = true
facebookLogo.widthAnchor.constraint(equalToConstant: 25).isActive = true
googleButton.leadingAnchor.constraint(equalTo: emailButton.leadingAnchor).isActive = true
googleButton.trailingAnchor.constraint(equalTo: emailButton.trailingAnchor).isActive = true
googleButton.bottomAnchor.constraint(equalTo: facebookButton.bottomAnchor, constant: 55 + 10).isActive = true
googleButton.heightAnchor.constraint(equalToConstant: 50).isActive = true
googleLogo.centerYAnchor.constraint(equalTo: googleButton.centerYAnchor).isActive = true
googleLogo.leadingAnchor.constraint(equalTo: googleButton.leadingAnchor, constant: 10).isActive = true
googleLogo.heightAnchor.constraint(equalToConstant: 25).isActive = true
googleLogo.widthAnchor.constraint(equalToConstant: 25).isActive = true
appleButton.leadingAnchor.constraint(equalTo: emailButton.leadingAnchor).isActive = true
appleButton.trailingAnchor.constraint(equalTo: emailButton.trailingAnchor).isActive = true
appleButton.bottomAnchor.constraint(equalTo: googleButton.bottomAnchor, constant: 55 + 10).isActive = true
appleButton.heightAnchor.constraint(equalToConstant: 50).isActive = true
appleLogo.centerYAnchor.constraint(equalTo: appleButton.centerYAnchor).isActive = true
appleLogo.leadingAnchor.constraint(equalTo: appleButton.leadingAnchor, constant: 10).isActive = true
appleLogo.heightAnchor.constraint(equalToConstant: 25).isActive = true
appleLogo.widthAnchor.constraint(equalToConstant: 25).isActive = true
documentsLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 10).isActive = true
documentsLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -10).isActive = true
documentsLabel.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -5).isActive = true
}
实际上这取决于您希望布局在每个设备中的显示方式,因此如果您希望所有元素的高度固定,那么您应该将所有元素包装在一个滚动视图中,该滚动视图将为小型设备滚动并在不存在时执行大型设备,或者如果您需要使元素适合所有设备的屏幕,那么您应该使高度限制与屏幕高度成比例
试试这个。
它使用了几个百分比的高度(基于您在 iPhone 8 屏幕上的原始布局)。
我没有更改您现有的任何代码。只需添加以下 func
并将您的呼叫从:
setupViews()
到
setupViewsDon()
应该从评论中清楚地知道您可能想要进行任何调整...但希望这会让您接近您的目标 - 也许您会发现一些提示以供将来使用:
func setupViewsDon(){
// setting these properties here, so I don't have to change your original initialization
willkommenLabel.numberOfLines = 1
willkommenLabel.adjustsFontSizeToFitWidth = true
willkommenLabel.minimumScaleFactor = 0.5
textLabel.numberOfLines = 2
textLabel.adjustsFontSizeToFitWidth = true
textLabel.minimumScaleFactor = 0.5
// prevent willkommenLabel from being compressed or streched
willkommenLabel.setContentHuggingPriority(.required, for: .vertical)
willkommenLabel.setContentCompressionResistancePriority(.required, for: .vertical)
// prevent oderLabel from being compressed or streched
oderLabel.setContentHuggingPriority(.required, for: .vertical)
oderLabel.setContentCompressionResistancePriority(.required, for: .vertical)
// prevent documentsLabel from being compressed or streched
documentsLabel.setContentHuggingPriority(.required, for: .vertical)
documentsLabel.setContentCompressionResistancePriority(.required, for: .vertical)
view.addSubview(backgroundImage)
view.addSubview(willkommenLabel)
view.addSubview(textLabel)
view.addSubview(emailButton)
emailButton.addSubview(emailImage)
view.addSubview(oderLabel)
view.addSubview(lineLeft)
view.addSubview(lineRight)
view.addSubview(facebookButton)
facebookButton.addSubview(facebookLogo)
view.addSubview(googleButton)
googleButton.addSubview(googleLogo)
view.addSubview(appleButton)
appleButton.addSubview(appleLogo)
view.addSubview(documentsLabel)
backgroundImage.topAnchor.constraint(equalTo: view.topAnchor, constant: -20).isActive = true
backgroundImage.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 20).isActive = true
backgroundImage.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: -20).isActive = true
backgroundImage.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 20).isActive = true
// add a layout guide for percentage top spacing
let topSpaceGuide = UILayoutGuide()
view.addLayoutGuide(topSpaceGuide)
// based on iPhone 8 ... 80-pts from top
// will be shorter on smaller devices, taller on larger devices
topSpaceGuide.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
topSpaceGuide.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 80.0 / 667.0).isActive = true
willkommenLabel.topAnchor.constraint(equalTo: topSpaceGuide.bottomAnchor).isActive = true
willkommenLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 30).isActive = true
willkommenLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -30).isActive = true
// textLabel top constrained to willkommenLabel bottom
textLabel.topAnchor.constraint(equalTo: willkommenLabel.bottomAnchor, constant: 0).isActive = true
textLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 30).isActive = true
textLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -30).isActive = true
// textLabel height = a percentage of view height using 100-pts based on an iPhone 8
// priority = .defaultHigh so it can be compressed if needed (on smaller devices)
let c = textLabel.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 100.0 / 667.0)
c.priority = .defaultHigh
c.isActive = true
// set email button height
emailButton.heightAnchor.constraint(equalToConstant: 50).isActive = true
// set other button heights equal to emailButton
facebookButton.heightAnchor.constraint(equalTo: emailButton.heightAnchor).isActive = true
googleButton.heightAnchor.constraint(equalTo: emailButton.heightAnchor).isActive = true
appleButton.heightAnchor.constraint(equalTo: emailButton.heightAnchor).isActive = true
// add the logo images to the buttons, and make their heights relative to button heights
// in case you want to change the button heights
for (btn, img) in [(emailButton, emailImage), (facebookButton, facebookLogo), (googleButton, googleLogo), (appleButton, appleLogo)] {
btn.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 30).isActive = true
btn.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -30).isActive = true
btn.addSubview(img)
img.centerYAnchor.constraint(equalTo: btn.centerYAnchor).isActive = true
img.leadingAnchor.constraint(equalTo: btn.leadingAnchor, constant: 10).isActive = true
img.heightAnchor.constraint(equalTo: btn.heightAnchor, multiplier: 0.5).isActive = true
img.widthAnchor.constraint(equalTo: img.heightAnchor).isActive = true
}
emailButton.topAnchor.constraint(equalTo: textLabel.bottomAnchor, constant: 20).isActive = true
oderLabel.topAnchor.constraint(equalTo: emailButton.bottomAnchor, constant: 15).isActive = true
facebookButton.topAnchor.constraint(equalTo: oderLabel.bottomAnchor, constant: 15).isActive = true
googleButton.topAnchor.constraint(equalTo: facebookButton.bottomAnchor, constant: 10).isActive = true
appleButton.topAnchor.constraint(equalTo: googleButton.bottomAnchor, constant: 10).isActive = true
// make sure appleButton stays above documentsLabel
appleButton.bottomAnchor.constraint(lessThanOrEqualTo: documentsLabel.topAnchor, constant: -20.0).isActive = true
// horizontal arrangement of oderLabel and left/right lines
oderLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
oderLabel.widthAnchor.constraint(equalToConstant: 60).isActive = true
lineLeft.centerYAnchor.constraint(equalTo: oderLabel.centerYAnchor).isActive = true
lineLeft.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 30).isActive = true
lineLeft.trailingAnchor.constraint(equalTo: oderLabel.leadingAnchor).isActive = true
lineRight.centerYAnchor.constraint(equalTo: oderLabel.centerYAnchor).isActive = true
lineRight.leadingAnchor.constraint(equalTo: oderLabel.trailingAnchor).isActive = true
lineRight.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -30).isActive = true
// documentsLabel stay at bottom
documentsLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 10).isActive = true
documentsLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -10).isActive = true
documentsLabel.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -5).isActive = true
}
如果您希望您的设计在所有设备上都能完美运行,那么您必须尽可能避免设置常量值,除非有必要,这里您设置高度和填充固定数字,尝试将它们设置为与屏幕相关大小,例如,您可以在此处设置视图中的所有按钮并将其高度设置为屏幕的一半:
Let height = view.frame.size.height / 2
buttonView.heightAnchor.constrains(equalTo: height).isActive = true
并且还将按钮插入到 stackView 中,覆盖按钮视图并将其设置为均匀填充按钮。因此,您将平等地拥有所有按钮而不是硬编码,以及与运行该应用程序的任何设备的屏幕尺寸相关的按钮动态视图