Evgenii
Evgenii

Reputation: 37349

How to find out the distance from the bottom safe area edge to the bottom of the screen?

I need to calculate the distance between the bottom anchor of the safe area and the bottom of the screen. Is there a way to do that in code given a view?

enter image description here

Upvotes: 15

Views: 11037

Answers (4)

Mike Zriel
Mike Zriel

Reputation: 1865

Here is a solution that works well on tableviews with adding a bottomView for buttons:

    let buttonsView = UIView()
    buttonsView.translatesAutoresizingMaskIntoConstraints = false
    buttonsView.backgroundColor = .secondarySystemBackground
    self.tableView.addSubview(buttonsView)
    
    let window = UIApplication.shared.windows.filter {$0.isKeyWindow}.first
    let bottomPadding = window?.safeAreaInsets.bottom ?? 0
    
    buttonsView.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor, constant: bottomPadding ).isActive = true
    buttonsView.leftAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.leftAnchor).isActive = true
    buttonsView.rightAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.rightAnchor).isActive = true
    buttonsView.heightAnchor.constraint(equalToConstant: 88.0 + bottomPadding ).isActive = true

Upvotes: 0

user6788419
user6788419

Reputation: 7350

Try this one

if #available(iOS 11.0, *) {
    let window = UIApplication.shared.keyWindow
    let bottomPadding = window?.safeAreaInsets.bottom
}

Upvotes: 34

jlmurph
jlmurph

Reputation: 1090

To re-iterate previous answers. Pin a subview to the bottom of the view of a UIViewController. Then pin a second one to the view.safeAreaLayoutGuide.bottomAnchor anchor of the view. With both subviews pinning the top, leading and trailing anchors of the parent view. Then, I would assume in viewDidAppear, you could print out the difference between the two subview's frame.maxY values. This should give you the difference.

let viewA = UIView()

let viewB = UIView()

override func viewDidLoad() {

    view.addSubview(viewA)
    view.addSubview(viewB)
    viewA.translateAutoResizingMasksIntoConstraints = false
    viewB.translateAutoResizingMasksIntoConstraints = false


        if #available(iOS 11.0, *) {
            NSLayoutConstraint.activate([viewA.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 0),
                                         viewA.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 0),
                                         viewA.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: 0),
                                         viewA.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: 0),
                                         viewB.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 0),
                                         viewB.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 0),
                                         viewB.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: 0),
                                         viewB.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 0)])
        } else {
            // Fallback on earlier versions
        }

}

override func viewDidAppear() {

    super.viewDidAppear()
    print("Safe Distance Value is:\(viewA.frame.maxY - viewB.frame.maxY)")

}

As a reference for others, the value appears to be 34 on an iPhone X simulator

Upvotes: 1

jefflovejapan
jefflovejapan

Reputation: 2121

You could try pinning a subview (clear , hidden or whatever) to the bottom of the safeAreaLayoutGuide and calculate the difference between the bottom of this view and your view controller's view in viewDidLayoutSubviews.

class ViewController: UIViewController {
    let measuringView = UIView()
    override func viewDidLoad() {
        super.viewDidLoad()
        measuringView.backgroundColor = .magenta
        measuringView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(measuringView)
        let vConstraint = measuringView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor)
        let heightConstraint = measuringView.heightAnchor.constraint(equalToConstant: 34)
        var constraints = NSLayoutConstraint.constraints(withVisualFormat: "|[measuring]|", options: [], metrics: nil, views: ["measuring": measuringView])
        constraints.append(vConstraint)
        constraints.append(heightConstraint)
        NSLayoutConstraint.activate(constraints)
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        let measuringBottom = measuringView.frame.origin.y + measuringView.frame.height
        let viewBottom = view.bounds.height
        let distance = abs(measuringBottom - viewBottom)
        print("distance is \(distance) points")
    }
}

measuring distance

Upvotes: 1

Related Questions