2

I just created a simple red view and create 4 constraints for it (top, left, right, bottom). I am trying to make adaptive layout using size classes, but cannot achieve correct layout in "landscape right" orientation:

  1. In portrait mode it's all correct. Bottom, left, right edges to superview's edges, top edge to safe area's top.
  2. In landscape left mode it's all correct. Top, right edges to superviews's edges, left and bottom to safe area's edges.
  3. But in landscape right mode layout is not correct. I expect, that left edge will be equal to superview's left edge, but actually it equal to safe area. Same thing with right edge: I expect that it will be equal to safe area's edge, but actually it equal to superview's edge. How to fix that?

Interface Builder Screenshot Portrait Mode Landscape Left Landscape Right

Gikas
  • 961
  • 1
  • 8
  • 20

4 Answers4

1

First make separate constant only for top constraint for size classes. Look at my images. Then create an outlet for leading and trailing constraints.

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var conTrailing: NSLayoutConstraint!
    @IBOutlet weak var conLeading: NSLayoutConstraint!     

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        self.setOrientationAllignment()
    }

    func setOrientationAllignment() {
        switch UIDevice.current.orientation {
        case .portrait:
            self.conLeading.constant = 0
            self.conTrailing.constant = 0
        case .landscapeLeft:
            self.conLeading.constant = 40
            self.conTrailing.constant = 0
        case .landscapeRight:
            self.conLeading.constant = 00
            self.conTrailing.constant = 40
        default:
            break
        }
        self.view.layoutSubviews() //  no  need  now
        self.view.layoutIfNeeded()
    }        

    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        super.viewWillTransition(to: size, with: coordinator)        
        self.setOrientationAllignment()
    }
}

Xcode screenshots

shim
  • 9,289
  • 12
  • 69
  • 108
Fisky
  • 114
  • 5
  • It makes sense that constraints in code can be some duck tape. I thought there was some automatic way to do this via Interface Builder – Gikas Jun 21 '19 at 19:23
0

As far as I understood what are you trying to achieve is whenever a phone is in landscape position, your red view's edge should be equal to superview's corresponding edge on the side where there is a phone's bottom. If so you can create 4 constraints, 2 for right side and 2 for left side.

Let's consider 2 constraints of red view's leading edge: 1) Red view's leading edge is equal to superview's leading edge 2) Red view's leading edge is equal to SafeArea

All constraints have default priority of 999

Then, what you could do in your view controller is:

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransition(to: size, with: coordinator)

    let lowPriority = UILayoutPriority(rawValue: 250)
    let highPriority = UILayoutPriority(rawValue: 999)

    switch UIDevice.current.orientation {
    case .landscapeLeft:
        leftEdgeToSafeAreaConstraint.priority = highPriority
        rightEdgeToSafeAreaConstraint.priority = lowPriority

        leftEdgeToSuperviewConstraint.priority = lowPriority
        rightEdgeToSuperviewConstraint.priority = highPriority
    case .landscapeRight:
        leftEdgeToSafeAreaConstraint.priority = lowPriority
        rightEdgeToSafeAreaConstraint.priority = highPriority

        leftEdgeToSuperviewConstraint.priority = highPriority
        rightEdgeToSuperviewConstraint.priority = lowPriority
    default:
        leftEdgeToSafeAreaConstraint.priority = highPriority
        rightEdgeToSafeAreaConstraint.priority = highPriority

        leftEdgeToSuperviewConstraint.priority = lowPriority
        rightEdgeToSuperviewConstraint.priority = lowPriority
    }
}
vdmzz
  • 261
  • 1
  • 4
  • It makes sense that constraints in code can be some duck tape. I thought there was some automatic way to do this via Interface Builder – Gikas Jun 21 '19 at 19:23
0

I am struggling with device rotations using left, right, top , bottom anchors.

For right landscape you should be quiet for top edge and status bar.

If you understand correctly your view hierarchy you can use like these code example:

        let deleteButtonImage = UIImage(named: "DeleteButton") as UIImage?  
        let deleteButtonImageSize: CGSize = CGSize(width: 295, height: 45)
        let deleteButton = UIButton(type: UIButton.ButtonType.custom)
        deleteButton.translatesAutoresizingMaskIntoConstraints = false
        deleteButton.tintColor = .white
        deleteButton.frame = CGRect(x: 0, y: 0, width: 250, height: 135)
        deleteButton.setImage(deleteButtonImage, for: .normal)

        deleteButton.imageEdgeInsets = UIEdgeInsets(
            top: (deleteButton.frame.size.height - deleteButtonImageSize.height) / 2,
            left: (deleteButton.frame.size.width - deleteButtonImageSize.width) / 2.5,
            bottom: (deleteButton.frame.size.height - deleteButtonImageSize.height) / 2,
            right: (deleteButton.frame.size.width - deleteButtonImageSize.width) / 2.5)


        scrollView.addSubview(deleteButton)

        deleteButton.rightAnchor.constraint(equalTo: self.view.rightAnchor).isActive = true
        deleteButton.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: -150).isActive = true
        deleteButton.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 370).isActive = true
        deleteButton.widthAnchor.constraint(equalTo: self.scrollView.safeAreaLayoutGuide.widthAnchor).isActive = true
        deleteButton.heightAnchor.constraint(equalToConstant: 45).isActive = true

   }
Emre Değirmenci
  • 715
  • 6
  • 22
  • It makes sense that constraints in code can be some duck tape. I thought there was some automatic way to do this via Interface Builder – Gikas Jun 21 '19 at 19:23
0

Set top, left, right margins to 0 align to Safe Area. and bottom to 0 with Superview.

change safe area to superview

Community
  • 1
  • 1
niku
  • 472
  • 3
  • 12