我在UIButton
的中间创建了一个TabBarController
,但由于手机底部的安全区域,它在iPhone X上显示不正确。
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
//Frame mic button
micButton.frame = CGRect.init(x: self.tabBar.center.x - 62, y: self.view.bounds.height - 94, width: 124, height: 124)
micButton.layer.cornerRadius = 62
}
在不触及安全区域的情况下绘制此UIButton
的正确方法是什么。
答案 0 :(得分:1)
安全区域,特别是safeAreaLayoutGuide
,与约束有关。
有各种方法来编码自动布局约束(Visual Format Layout或VFL,explicit - and wordy - NSLayoutConstraints
),但我更喜欢使用“layout anchors”。
任何布局的基本思路是位置和尺寸。给出宽度/高度和x / y轴值的东西,你就得到了它。非常像帧。
所以基本的“锚定”方式来阐述这个:
micButton.frame = CGRect.init(x: self.tabBar.center.x - 62, y: self.view.bounds.height - 94, width: 124, height: 124)
会是这样的:
let micButton = UIButton()
micButton.translatesAutoresizingMaskIntoConstraints = false
micButton.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -94).isActive = true
micButton.widthAnchor.constraint(equalToConstant: 124).isActive = true
micButton.heightAnchor.constraint(equalToConstant: 124).isActive = true
micButton.centerXAnchor.constraint(equalTo: view.centerXAnchor, constant: -62).isActive = true
一些注意事项:
虽然代码比使用框架更多,但您获得的是屏幕尺寸的一致性。
但是你需要更多 - 你需要为iPhone X安全区域编码。 Apple有两个工具:layoutMarginsGuide
和safeAreaLayoutGuide
。前者是在iOS 9中引入的(以及更简单的layoutGuide
和布局锚点),后者是在iOS 11中引入的。
[我的假设,可能是安全的,是所有iPhone X设备都将运行iOS 11或更高版本。由于此设备实际上只需要“安全区域”,因此您需要以下内容。]
边距适用于所有设备的前导/尾随(或水平)边缘。它们也适用于顶部/底部(或垂直)边缘。但对于iPhone X,你需要关注不同的顶部/底部,因此是“安全区域”。
let layoutGuideTop = UILayoutGuide()
let layoutGuideBottom = UILayoutGuide()
view.addLayoutGuide(layoutGuideTop)
view.addLayoutGuide(layoutGuideBottom)
let margins = view.layoutMarginsGuide
view.addLayoutGuide(margins)
if #available(iOS 11, *) {
let guide = view.safeAreaLayoutGuide
layoutGuideTop.topAnchor.constraintEqualToSystemSpacingBelow(guide.topAnchor, multiplier: 1.0).isActive = true
layoutGuideBottom.bottomAnchor.constraintEqualToSystemSpacingBelow(guide.bottomAnchor, multiplier: 1.0).isActive = true
} else {
layoutGuideTop.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor).isActive = true
layoutGuideBottom.bottomAnchor.constraint(equalTo: bottomLayoutGuide.topAnchor).isActive = true
}
上面的代码段会根据iOS版本生成正确的上/下边距变量(layoutGuideTop
和layoutGuideBottom
)。从那里你可以调整底部锚点:
micButton.bottomAnchor.constraint(equalTo: laytouGuideBottom, constant: -94).isActive = true
应将micButton
设置为高于底部安全区域94个点。
以下是一些可以帮助您了解布局锚点和指南的链接:
编辑:
关于约束的最后一点说明。由于您不依赖于帧值,因此所有这些代码最好放在viewDidLoad
中,因为布局引擎将适当地确定所有内容(并且可以多次调用viewDidLayoutSubviews
)。
答案 1 :(得分:1)
试试这个:
添加UITabViewController的类
micButton.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(micButton)
if #available(iOS 11, *) {
let guide = view.safeAreaLayoutGuide
micButton.centerXAnchor.constraint(equalTo: guide.centerXAnchor).isActive = true
micButton.bottomAnchor.constraint(equalTo: guide.bottomAnchor).isActive = true
micButton.heightAnchor.constraint(equalToConstant: 64).isActive = true
micButton.widthAnchor.constraint(equalToConstant: 64).isActive = true
} else {
NSLayoutConstraint(item: micButton, attribute: .centerX, relatedBy: .equal, toItem: view, attribute: .centerX, multiplier: 1.0, constant: 0).isActive = true
NSLayoutConstraint(item: micButton, attribute: .bottom, relatedBy: .equal, toItem: view, attribute: .bottom, multiplier: 1, constant: 0).isActive = true
micButton.heightAnchor.constraint(equalToConstant: 64).isActive = true
micButton.widthAnchor.constraint(equalToConstant: 64).isActive = true
}
答案 2 :(得分:0)
感谢@dfd指导,这就是我作为一种解决方法的方式。我刚检查了使用该应用程序的手机是否具有与iPhoneX相同的屏幕尺寸,我只是在限制条件下进行了更改。
override func viewDidLoad() {
super.viewDidLoad()
//Frame mic button
micButton.frame = CGRect.init(x: self.tabBar.center.x - 62, y: self.view.bounds.height - 94, width: 124, height: 124)
micButton.layer.cornerRadius = 62
micButton.translatesAutoresizingMaskIntoConstraints = false
micButton.setBackgroundImage(#imageLiteral(resourceName: "micIcon"), for: .normal)
//Add to tabbar view
self.view.insertSubview(micButton, aboveSubview: self.tabBar)
if UIDevice().userInterfaceIdiom == .phone {
if UIScreen.main.nativeBounds.height == 2436 {
//iPhoneX Device
micButton.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 0).isActive = true
micButton.widthAnchor.constraint(equalToConstant: 124).isActive = true
micButton.heightAnchor.constraint(equalToConstant: 124).isActive = true
micButton.centerXAnchor.constraint(equalTo: self.tabBar.centerXAnchor, constant: 0).isActive = true
} else {
//Not an iPhoneX Device
micButton.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 25).isActive = true
micButton.widthAnchor.constraint(equalToConstant: 124).isActive = true
micButton.heightAnchor.constraint(equalToConstant: 124).isActive = true
micButton.centerXAnchor.constraint(equalTo: self.tabBar.centerXAnchor, constant: 0).isActive = true
}
}
// Do any additional setup after loading the view.
}
答案 3 :(得分:0)
此代码可帮助您解决问题。
micButton.bottomAnchor.constraint(equalTo:view.safeAreaLayoutGuide.bottomAnchor).isActive = true