I'm getting the hang of using the safe area when using custom UI elements in .xib
/.storyboard
.
I now have the case where I have a UIButton subclass that's used everywhere throughout the app. Since it's just a subclass (and not a custom class in .xib
) I'm not sure how I would update this to fit my needs.
See the following photo:
Here the yellow is the UIButton. On 'regular' iPhones this yellow is the bottom of the screen.
What I'm trying to achieve is to have the button go all the way to the bottom of the safe area, while still being in the same position (above the safe area).
Normally I would constraint the button to superview.bottom
, and in the button's .xib
constraint the content (titleLabel, buttonImage, etc) to safearea.bottom
.
Since that's not possible here, how would I do that?
I tried adding the constraints programatically in the UIButton subclass, but to not avail.
Example:
if #available(iOS 11.0, *) {
NSLayoutConstraint.activate([
(titleLabel?.topAnchor.constraint(equalTo: self.safeAreaLayoutGuide.topAnchor))!,
(titleLabel?.bottomAnchor.constraint(equalTo: self.safeAreaLayoutGuide.bottomAnchor))!
])
} else {
// Fallback on earlier versions
}
Thanks in advance!
You can use the following approach for this,
UIView
.UILabel
to the above created view
as a subView
.UIButton
to the above created view
as a subView
.Apply proper layout constraints
to get the desirable UI.
func addSaveButton() {
let height: CGFloat = 60 + self.view.safeAreaInsets.bottom //Height based on safe area
//Custom View
let customView = UIView(frame: CGRect.init(x: 0, y: self.view.bounds.height - height, width: self.view.bounds.width, height: height))
customView.backgroundColor = #colorLiteral(red: 0.9529411793, green: 0.6862745285, blue: 0.1333333403, alpha: 1)
//Save Label
let label = UILabel()
label.text = "Save"
label.textColor = UIColor.black
//Button
let button = UIButton(frame: customView.bounds)
button.addTarget(self, action: #selector(onTapSaveButton), for: .touchUpInside)
//Add label, button as subview in customView
customView.addSubview(label)
customView.addSubview(button)
self.view.addSubview(customView)
customView.translatesAutoresizingMaskIntoConstraints = false
label.translatesAutoresizingMaskIntoConstraints = false
button.translatesAutoresizingMaskIntoConstraints = false
//Add constraints
NSLayoutConstraint.activate([
self.view.leadingAnchor.constraint(equalTo: customView.leadingAnchor),
customView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor),
customView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor),
customView.heightAnchor.constraint(equalToConstant: height),
label.topAnchor.constraint(equalTo: customView.topAnchor, constant: 10),
label.trailingAnchor.constraint(equalTo: customView.trailingAnchor, constant: -10),
button.topAnchor.constraint(equalTo: customView.topAnchor),
button.leadingAnchor.constraint(equalTo: customView.leadingAnchor),
button.trailingAnchor.constraint(equalTo: customView.trailingAnchor),
button.bottomAnchor.constraint(equalTo: customView.bottomAnchor)
])
}
@objc func onTapSaveButton() {
print("Save button pressed")
}
In iPhone-X
In iPhone-8
Approach 2:
You can follow a bit more simplified approach by playing with the button's
titleEdgeInsets
.
func addSaveButton() {
let height: CGFloat = 60 + self.view.safeAreaInsets.bottom
//Button
let button = UIButton(frame: CGRect.init(x: 0, y: UIScreen.main.bounds.height - height, width: UIScreen.main.bounds.width, height: height))
button.setTitle("Save", for: .normal)
button.backgroundColor = #colorLiteral(red: 0.9529411793, green: 0.6862745285, blue: 0.1333333403, alpha: 1)
button.contentHorizontalAlignment = .right
button.contentVerticalAlignment = .top
button.titleEdgeInsets.top = 10
button.titleEdgeInsets.right = 10
button.addTarget(self, action: #selector(onTapSaveButton), for: .touchUpInside)
self.view.addSubview(button)
button.translatesAutoresizingMaskIntoConstraints = false
//Add constraints
NSLayoutConstraint.activate([
self.view.leadingAnchor.constraint(equalTo: button.leadingAnchor),
button.bottomAnchor.constraint(equalTo: self.view.bottomAnchor),
button.trailingAnchor.constraint(equalTo: self.view.trailingAnchor),
button.heightAnchor.constraint(equalToConstant: height)
])
}
You can do the same thing in storyboard/subclassing
easily. I think this one is better than the previous one.
Approach 3:
Subclass UIButton
and use it to create your button programatically.
class CustomButton: UIButton {
override func draw(_ rect: CGRect) {
self.contentHorizontalAlignment = .right
self.contentVerticalAlignment = .top
self.titleEdgeInsets.top = 10
self.titleEdgeInsets.right = 10
}
}