Different layouts in portrait and landscape mode

后端 未结 9 1626
别跟我提以往
别跟我提以往 2020-12-28 14:16

Let\'s assume I have this layout design on an iPad Portrait.

But I would like to have it this way when the iPad is in landscape:

Is it possible to

相关标签:
9条回答
  • 2020-12-28 15:12

    My task was the similar in general. I was needing portrait and landscape constraints for both iPhone and iPad. Moreover, yellow and grey views location should be the same in general, but the width of yellow view should be different in iPhone landscape and in iPad landscape (40% of the screen in iPhone and 60% of the screen in iPad):

    Constraints for iPhone orientations I've set using traits collections and defining for each constraint for what collection it should be installed. For iPhone there are wChR (portrait) and wChC (landscape). Or wC with hAny:

    But for landscape and portrait orientations on iPad the single traits collections are used (wRhR) therefore the way used for iPhone is not suitable. To change constraints for these cases I wares up two constraints sets (the first for iPad in landscape and the second for iPad in portrait):

    @property (strong, nonatomic) IBOutletCollection(NSLayoutConstraint) NSArray *ipadLandscapeConstraints;
    @property (strong, nonatomic) IBOutletCollection(NSLayoutConstraint) NSArray *ipadPortraitConstraints;
    

    Note: 1. To do it select several required constraints in storyboard and wire up them to your .m file. To see what constraints were added to array, click ‘+’ button in he left for the property in .m file: 2. I used constraints priority to solve constraints conflicts for iPad

    Finally, I’ve implemented configConstraints method to switch constraints sets according to iPad orientation and have overridden viewWillTransitionToSize method:

    - (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
        [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
        [self configConstraints];
    }
    
    - (void)configConstraints {
        if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
            // iPad landscape orientation
            if (UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation)) {
                [NSLayoutConstraint deactivateConstraints:self.ipadPortraitConstraints];
                [NSLayoutConstraint activateConstraints:self.ipadLandscapeConstraints];
            }
            // iPad portrait orientation
            else {
                [NSLayoutConstraint deactivateConstraints:self.ipadLandscapeConstraints];
                [NSLayoutConstraint activateConstraints:self.ipadPortraitConstraints];
            }
            [self.view layoutIfNeeded];
        }
    }
    

    May be it would be required to call configConstraints method in other places where the view is loading or appearing, but the base idea is described above.

    0 讨论(0)
  • 2020-12-28 15:14

    my two cents.. swift 5:

    (pls connect outlet....)

    //
    //  ViewController.swift
    //  AutoLayoutSampleOnRotation
    //
    //  Created by ing.conti on 13/09/2019.
    //  Copyright © 2019 ing.conti. All rights reserved.
    //
    
    import UIKit
    
    class ViewController: UIViewController {
        @IBOutlet weak var redView: UIView!
        @IBOutlet weak var yellowView: UIView!
    
        private var red_TopPortrait : NSLayoutConstraint?
        private var red_TopLandscape : NSLayoutConstraint?
    
        private var red_LeftPortrait : NSLayoutConstraint?
        private var red_LeftLandscape : NSLayoutConstraint?
    
        private var red_RightPortrait : NSLayoutConstraint?
        private var red_RightLandscape : NSLayoutConstraint?
    
        private var red_BottomPortrait : NSLayoutConstraint?
        private var red_BottomLandscape : NSLayoutConstraint?
    
        private var red_HeightPortrait : NSLayoutConstraint?
        private var red_WidthLandscape : NSLayoutConstraint?
    
    
        ///
        private var yellow_TopPortrait : NSLayoutConstraint?
        private var yellow_TopLandscape : NSLayoutConstraint?
    
        private var yellow_LeftPortrait : NSLayoutConstraint?
        private var yellow_LeftLandscape : NSLayoutConstraint?
    
        private var yellow_RightPortrait : NSLayoutConstraint?
        private var yellow_RightLandscape : NSLayoutConstraint?
    
        private var yellow_BottomPortrait : NSLayoutConstraint?
        private var yellow_BottomLandscape : NSLayoutConstraint?
    
    
        private let H_SpaceBetween = CGFloat(20)
        private let V_SpaceBetween = CGFloat(50)
    
        override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view.
    
    
            redView.translatesAutoresizingMaskIntoConstraints = false
            yellowView.translatesAutoresizingMaskIntoConstraints = false
    
            buildConstraintsForRed()
            buildConstraintsForYellow()
    
            applyConstraints()
        }
    
    
    
        final private func buildConstraintsForRed(){
    
            let portraitTopMargin = CGFloat(70)
            let portraitLeftMargin = CGFloat(70)
            let portraitRightMargin = CGFloat(70)
    
            let landscapeTopMargin = CGFloat(70)
            let landscapeLeftMargin = CGFloat(70)
            let landscapeBottomMargin = CGFloat(70)
    
            // TOP P
            red_TopPortrait = NSLayoutConstraint(item: redView as Any,
                                                 attribute: .top,
                                                 relatedBy: .equal,
                                                 toItem: self.view,
                                                 attribute: .top,
                                                 multiplier: 1,
                                                 constant: portraitTopMargin)
            red_TopPortrait!.identifier = "red_TopPortrait"
    
            // LEFT-Heading P
            red_LeftPortrait = NSLayoutConstraint(item: redView as Any,
                                                  attribute: .leading,
                                                  relatedBy: .equal,
                                                  toItem: self.view,
                                                  attribute: .leading,
                                                  multiplier: 1,
                                                  constant: portraitLeftMargin)
            red_LeftPortrait!.identifier = "red_LeftPortrait"
    
            // RIGHT - trailing P
            red_RightPortrait = NSLayoutConstraint(item: redView as Any,
                                                   attribute: .trailing,
                                                   relatedBy: .equal,
                                                   toItem: self.view,
                                                   attribute: .trailing,
                                                   multiplier: 1,
                                                   constant: -portraitRightMargin)
            red_RightPortrait!.identifier = "red_RightPortrait"
    
            // BOTTOM: P
            red_BottomPortrait = NSLayoutConstraint(item: redView as Any,
                                                    attribute: .bottom,
                                                    relatedBy: .equal,
                                                    toItem:  yellowView,
                                                    attribute: .top,
                                                    multiplier: 1,
                                                    constant: -V_SpaceBetween)
            red_BottomPortrait!.identifier = "red_BottomPortrait"
    
            // HEIGHT: P
            red_HeightPortrait = NSLayoutConstraint(item: redView as Any,
                                              attribute: .height,
                                              relatedBy: .equal,
                                              toItem: self.view,
                                              attribute: .height,
                                              multiplier: 0.3,
                                              constant: 0)
            red_HeightPortrait?.identifier = "red_HeightPortrait"
    
    
    
            //LANDSCAPE
            // TOP L
            red_TopLandscape = NSLayoutConstraint(item: redView as Any,
                                                  attribute: .top,
                                                  relatedBy: .equal,
                                                  toItem: self.view,
                                                  attribute: .top,
                                                  multiplier: 1,
                                                  constant: landscapeTopMargin)
            red_TopLandscape!.identifier = "red_TopLandscape"
    
            // LEFT-Heading L
            red_LeftLandscape = NSLayoutConstraint(item: redView as Any,
                                                   attribute: .leading,
                                                   relatedBy: .equal,
                                                   toItem: self.view,
                                                   attribute: .leading,
                                                   multiplier: 1,
                                                   constant: landscapeLeftMargin)
            red_LeftLandscape!.identifier = "red_LeftLandscape"
    
    
            // RIGHT - trailing L
            red_RightLandscape = NSLayoutConstraint(item: redView as Any,
                                                    attribute: .trailing,
                                                    relatedBy: .equal,
                                                    toItem: yellowView,
                                                    attribute: .leading,
                                                    multiplier: 1,
                                                    constant: -H_SpaceBetween)
            red_RightLandscape!.identifier = "red_RightLandscape"
    
    
            // BOTTOM: L
            red_BottomLandscape = NSLayoutConstraint(item: redView as Any,
                                                     attribute: .bottom,
                                                     relatedBy: .equal,
                                                     toItem: self.view,
                                                     attribute: .bottom,
                                                     multiplier: 1,
                                                     constant: -landscapeBottomMargin)
            red_BottomLandscape?.identifier = "red_BottomLandscape"
    
            // Width L:
            red_WidthLandscape = NSLayoutConstraint(item: redView as Any,
                                              attribute: .width,
                                              relatedBy: .equal,
                                              toItem: self.view,
                                              attribute: .width,
                                              multiplier: 0.3,
                                              constant: 0)
            red_WidthLandscape!.identifier = "red_WidthLandscape"
        }
    
    
        final private func buildConstraintsForYellow(){
    
            let portraitLeftMargin = CGFloat(20)
            let portraitRightMargin = CGFloat(20)
            //let portraitHorizMargin = CGFloat(100)
            let portraitBottomMargin = CGFloat(20)
    
            let landscaspeTopMargin = CGFloat(20)
            let landscaspeRightMargin = CGFloat(20)
            let landscapeBottomMargin = CGFloat(20)
    
    
            // TOP P
            yellow_TopPortrait = NSLayoutConstraint(item: yellowView as Any,
                                                 attribute: .top,
                                                 relatedBy: .equal,
                                                 toItem: redView,
                                                 attribute: .bottom,
                                                 multiplier: 1,
                                                 constant: V_SpaceBetween)
            yellow_TopPortrait!.identifier = "yellow_TopPortrait"
    
            // LEFT-Heading P
            yellow_LeftPortrait = NSLayoutConstraint(item: yellowView as Any,
                                                     attribute: .leading,
                                                     relatedBy: .equal,
                                                     toItem: self.view,
                                                     attribute: .leading,
                                                     multiplier: 1,
                                                     constant: portraitLeftMargin)
            yellow_LeftPortrait!.identifier = "yellow_LeftPortrait"
    
            // RIGHT - trailing P
            yellow_RightPortrait = NSLayoutConstraint(item: yellowView as Any,
                                                      attribute: .trailing,
                                                      relatedBy: .equal,
                                                      toItem: self.view,
                                                      attribute: .trailing,
                                                      multiplier: 1,
                                                      constant: -portraitRightMargin)
            yellow_RightPortrait!.identifier = "yellow_RightPortrait"
    
            // BOTTOM: P
            yellow_BottomPortrait = NSLayoutConstraint(item: yellowView as Any,
                                                       attribute: .bottom,
                                                       relatedBy: .equal,
                                                       toItem: self.view,
                                                       attribute: .bottom,
                                                       multiplier: 1,
                                                       constant: -portraitBottomMargin)
            yellow_BottomPortrait!.identifier = "yellow_BottomPortrait"
    
            //LANDSSCAPE
            // TOP L
            yellow_TopLandscape = NSLayoutConstraint(item: yellowView as Any,
                                                  attribute: .top,
                                                  relatedBy: .equal,
                                                  toItem: self.view,
                                                  attribute: .top,
                                                  multiplier: 1,
                                                  constant: landscaspeTopMargin)
            yellow_TopLandscape!.identifier = "yellow_TopLandscape"
    
            // LEFT-Heading L
            yellow_LeftLandscape = NSLayoutConstraint(item: yellowView as Any,
                                                   attribute: .leading,
                                                   relatedBy: .equal,
                                                   toItem: self.redView,
                                                   attribute: .trailing,
                                                   multiplier: 1,
                                                   constant: H_SpaceBetween)
            yellow_LeftLandscape!.identifier = "yellow_LeftLandscape"
    
            // RIGHT - trailing L
            yellow_RightLandscape = NSLayoutConstraint(item: yellowView as Any,
                                                    attribute: .trailing,
                                                    relatedBy: .equal,
                                                    toItem: self.view,
                                                    attribute: .trailing,
                                                    multiplier: 1,
                                                    constant: -landscaspeRightMargin)
            yellow_RightLandscape!.identifier = "yellow_RightLandscape"
    
            // BOTTOM: L
            yellow_BottomLandscape = NSLayoutConstraint(item: yellowView as Any,
                                                     attribute: .bottom,
                                                     relatedBy: .equal,
                                                     toItem: self.view,
                                                     attribute: .bottom,
                                                     multiplier: 1,
                                                     constant: -landscapeBottomMargin)
            yellow_BottomLandscape!.identifier = "yellow_BottomLandscape"
        }
    
    
        final private  func removeRedConstraints() {
            if let c = red_LeftPortrait  {self.view.removeConstraint(c)}
            if let c = red_LeftLandscape  {self.view.removeConstraint(c)}
    
            if let c = red_RightPortrait  {self.view.removeConstraint(c)}
            if let c = red_RightLandscape  {self.view.removeConstraint(c)}
    
            if let c = red_TopPortrait  {self.view.removeConstraint(c)}
            if let c = red_TopLandscape  {self.view.removeConstraint(c)}
    
            if let c = red_BottomPortrait  {self.view.removeConstraint(c)}
            if let c = red_BottomLandscape  {self.view.removeConstraint(c)}
    
            if let c = red_HeightPortrait  {self.view.removeConstraint(c)}
            if let c = red_WidthLandscape  {self.view.removeConstraint(c)}
    
    
    
        }
    
    
        final private  func removeYellowConstraints() {
            if let c = yellow_LeftPortrait  {self.view.removeConstraint(c)}
            if let c = yellow_LeftLandscape  {self.view.removeConstraint(c)}
    
            if let c = yellow_RightPortrait  {self.view.removeConstraint(c)}
            if let c = yellow_RightLandscape  {self.view.removeConstraint(c)}
    
            if let c = yellow_TopPortrait  {self.view.removeConstraint(c)}
            if let c = yellow_TopLandscape  {self.view.removeConstraint(c)}
    
            if let c = yellow_BottomPortrait  {self.view.removeConstraint(c)}
            if let c = yellow_BottomLandscape  {self.view.removeConstraint(c)}
    
        }
    
    
        final private func applyPortraitConstraint(){
            removeRedConstraints()
            removeYellowConstraints()
            self.view.addConstraint(self.red_LeftPortrait!)
            self.view.addConstraint(self.red_RightPortrait!)
            self.view.addConstraint(self.red_TopPortrait!)
            self.view.addConstraint(self.red_BottomPortrait!)
    
            self.view.addConstraint(self.red_HeightPortrait!)
    
    
            self.view.addConstraint(self.yellow_LeftPortrait!)
            self.view.addConstraint(self.yellow_RightPortrait!)
            self.view.addConstraint(self.yellow_TopPortrait!)
            self.view.addConstraint(self.yellow_BottomPortrait!)
        }
    
        final private func applyLandscapeConstraint(){
            removeRedConstraints()
            removeYellowConstraints()
            self.view.addConstraint(self.red_LeftLandscape!)
            self.view.addConstraint(self.red_RightLandscape!)
            self.view.addConstraint(self.red_TopLandscape!)
            self.view.addConstraint(self.red_BottomLandscape!)
    
            self.view.addConstraint(self.red_WidthLandscape!)
    
            self.view.addConstraint(self.yellow_LeftLandscape!)
            self.view.addConstraint(self.yellow_RightLandscape!)
            self.view.addConstraint(self.yellow_TopLandscape!)
            self.view.addConstraint(self.yellow_BottomLandscape!)
        }
    
    
    
    
        final private func applyConstraints(){
    
            let orient = UIApplication.shared.statusBarOrientation
    
            switch orient {
            case .portrait:
                print("Portrait")
                self.applyPortraitConstraint()
                break
                // Do something
    
            default:
                print("LandScape")
                // Do something else
                self.applyLandscapeConstraint()
                break
            }
    
        }
    
    
    
    
    
    
        override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    
    
            coordinator.animate(alongsideTransition: { (UIViewControllerTransitionCoordinatorContext) -> Void in
    
                self.applyConstraints()
            }, completion: { (UIViewControllerTransitionCoordinatorContext) -> Void in
                print("rotation completed")
            })
    
            super.viewWillTransition(to: size, with: coordinator)
        }
    }
    

    0 讨论(0)
  • 2020-12-28 15:15

    iPAD don't have the size class for Landscape mode. I think the reason is that it is not needed in most of the cases. However one can activate and deactivate constraints when device orientation change like the accepted answer.

    The following can be helpful for iPhone user.

    Yes this is possible in interface builder with autolayout and size classes. You will not need to code.

    First you select size class wAny hAny

    Here is how to select size class.

    Add two views in your view controller. Red view on top and blue view below. Just like your first image.

    Constraints on red view are:

    • Top space to super view
    • Leading space to super view
    • Trailing space to super view
    • height = 50

    Constraints on blue view are:

    • vertical space to red view
    • leading space to super view
    • trailing space to super view
    • bottom space to super view

    This is all set for Potrait mode.

    Now you change size classes to wAny hCompact(The first two column in first row). this class is for iPhone landscape.

    Now you have to use install and uninstall concept.

    Constraints that will change for red view:

    • Uninstall its height constriant for (wAny hCompact) size class as:

    • Similary uninstall its Leading constraint. Add two new constraints to this red view in this class:
    • Bottom space to superview
    • Width constraint = 50

    This will make red view to right side with 50 width.

    Now constraint change for blue view:

    • Uninstall Its vertical spacing, trailing space.

    Add two new constraint:

    • Vertical space to super view
    • Trailing space to red View

    This will attach red view left of blue view.

    Hope it work for you.

    0 讨论(0)
提交回复
热议问题