纵向和横向模式下的不同布局

38
假设我在iPad纵向模式下有这个布局设计。

Screen1

但是当iPad处于横向模式时,我希望它是这样的: screen2 使用自动布局可以实现吗? 或者只需少量代码即可实现?

是的,这是可能的。诀窍是要保留所有约束条件的引用。然后当方向改变时,用新的约束条件替换所有约束条件并再次保留引用。 - dasdom
是不是更容易为纵向和横向分别使用两个Storyboard呢?@dasdom - Teja Nandamuri
1
@Mr.T 不行。这应该在一个故事板中完成。 - Sam B
请参考此答案,强制 iPad 横屏使用 height=compact 特征:https://dev59.com/Fl8d5IYBdhLWcg3wmDOf#28268200 - InfalibleCoinage
9个回答

29

首先,您需要通过代码实现此操作。您必须首先对动态约束进行IBoutlet

恒定约束://这些约束在两个方向上都保持不变

1- RedView顶部间距至SuperView

2- RedView右侧间距至SuperView

3- BlueView左侧间距至SuperView

4- BlueView底部间距至Superview

动态约束

竖屏约束:

1- RedView高度

2- RedView垂直间距至BlueView

3- RedView左侧间距至SuperView

4- BlueView右侧间距至SuperView

横屏约束:

1- RedView宽度

2- RedView水平间距至BlueView

3- RedView底部间距至SuperView

4- BlueView顶部间距至SuperView

现在,您需要覆盖在方向更改时调用的方法。

override func viewWillTransitionToSize(size: CGSize,   withTransitionCoordinator coordinator:    UIViewControllerTransitionCoordinator) {

    coordinator.animateAlongsideTransition({ (UIViewControllerTransitionCoordinatorContext) -> Void in

        let orient = UIApplication.sharedApplication().statusBarOrientation

        switch orient {
        case .Portrait:
            print("Portrait")
            self.ApplyportraitConstraint()
            break
            // Do something
        default:
            print("LandScape")
            // Do something else
            self.applyLandScapeConstraint()
            break
        }
        }, completion: { (UIViewControllerTransitionCoordinatorContext) -> Void in
            print("rotation completed")
    })
    super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
}

调用这两个函数

纵向方向函数

func ApplyportraitConstraint(){

 self.view.addConstraint(self.RedViewHeight)
 self.view.addConstraint(self.RedView_VerticalSpace_To_BlueView)
 self.view.addConstraint(self.RedView_LeadingSpace_To_SuperView)
 self.view.addConstraint(self.BlueView_TrailingSpace_To_SuperView)

 self.view.removeConstraint(self.RedViewWidth)
 self.view.removeConstraint(self.RedView_HorizontalSpace_To_BlueView)
 self.view.removeConstraint(self.RedView_BottomSpace_To_SuperView)          
 self.view.removeConstraint(self.BlueView_TopSpace_To_SuperView)


}

景观方向功能

    func applyLandScapeConstraint(){

    self.view.removeConstraint(self.RedViewHeight)
    self.view.removeConstraint(self.RedView_VerticalSpace_To_BlueView)
    self.view.removeConstraint(self.RedView_LeadingSpace_To_SuperView)
   self.view.removeConstraint(self.BlueView_TrailingSpace_To_SuperView)

    self.view.addConstraint(self.RedViewWidth)
    self.view.addConstraint(self.RedView_HorizontalSpace_To_BlueView)
    self.view.addConstraint(self.RedView_BottomSpace_To_SuperView)
    self.view.addConstraint(self.BlueView_TopSpace_To_SuperView)

}

竖屏截图: 输入图像描述 横屏截图: 输入图像描述

希望通过编码的布局管理帮助您理解它。 如果您还无法理解,请在

Github 上检查我的代码:

如果您收到了警告,请将高度和宽度的约束优先级设置为999。


是的,它可以工作,但我在控制台中收到了一些警告。 - Slavcho
2
修复:将高度和宽度约束优先级设置为999。 - Slavcho
1
在Storyboard中如何添加不同方向的不同布局约束? - Willjay
1
请问您能告诉我如何在Storyboard中更改方向,就像您在答案中所做的那样吗? - Jatin Dave
我已经将我的代码上传到Github。您可以在此处检查 https://github.com/mwaqasbhati/Portrait-LandScape-Different-Layouts。 - Muhammad Waqas Bhati
4
GitHub链接已失效。 - ingconti

14

iPad在横屏模式下没有大小类。我认为原因是因为大多数情况下都不需要。但是可以像被接受的答案一样,在设备方向改变时激活和停用约束。

对iPhone用户来说,以下内容可能会有所帮助。

是的,利用自动布局和大小类可以在界面构建器中实现此功能。您不需要编写代码。

首先,选择wAny hAny大小类。

这里是如何选择大小类。

enter image description here

在视图控制器中添加两个视图。红色视图在上方,蓝色视图在下方。就像您的第一张图片一样。

红色视图的约束条件为:

  • 顶部间距与超级视图
  • 前导空间与超级视图
  • 后置空间与超级视图
  • 高度 = 50

蓝色视图的约束条件为:

  • 相对红色视图的垂直间距
  • 前导空间与超级视图
  • 后置空间与超级视图
  • 底部间距与超级视图

这就是所有为肖像模式设置的内容。

现在,将大小类更改为wAny hCompact(第一行中的前两列)。这个类用于iPhone横屏模式。

现在,您必须使用安装卸载的概念。

将更改红色视图的约束条件:

  • 卸载其(wAny hCompact)大小类的高度约束,如下所示:

在这里输入图片描述

  • 同样地卸载其主要约束。
  • 为该类别中的红色视图添加两个新约束:
  • 底部空间与父视图
  • 宽度约束=50

这将使红色视图位于右侧并具有50的宽度。

现在蓝色视图的约束发生了变化:

  • 卸载其垂直间距和尾部间距。

添加两个新约束:

  • 垂直空间到父视图
  • 尾随空间到红色视图

这将把红色视图附加在蓝色视图左侧。

希望对您有所帮助。


1
你的答案适用于iPhone,但可悲的是iPad的大小类在纵向和横向时相同 :/ - Michaël Azevedo
1
@irfan,你不能在iPad上使用size classes,因为宽度和高度类别都被报告为“常规”。 - Peter Hornsby

5

我使用Obj-C实现了这个功能,并在我的github上发布了代码。解决方案涉及少量代码,大部分工作集中在自动布局和命名规范上…… README文件详细说明了我的做法。我在ViewController上使用的代码基本上是这个方法:

- (void)setUpViewConstraintsForInterfaceOrientation:(InterfaceOrientation)interfaceOrientation {
    self.lastOrientation = interfaceOrientation;
    if (interfaceOrientation == Landscape) {
        [NSLayoutConstraint deactivateConstraints:self.portraitConstraintsCollection];
        [NSLayoutConstraint activateConstraints:self.landscapeConstraintsCollection];
    } else if(interfaceOrientation == Portrait){
        [NSLayoutConstraint deactivateConstraints:self.landscapeConstraintsCollection];
        [NSLayoutConstraint activateConstraints:self.portraitConstraintsCollection];
    }
    [self.view layoutIfNeeded];
}

portraitConstraintsCollection和landscapeConstraintsCollection是IBOutletCollection属性,用于管理特定方向的约束条件。

而自动布局解决方案只需要安装和卸载约束条件(激活和停用),不需要添加或删除约束条件。


1
这听起来是一种干净的方法。我希望苹果允许我们在Storyboard中明确地创建不同方向的布局! - Deepak Sharma

4

我的任务基本上是相似的。我需要为iPhone和iPad提供肖像和横向的限制条件。此外,黄色和灰色视图的位置应该是基本相同的,但是在iPhone横向和iPad横向上,黄色视图的宽度应该不同(在iPhone上为屏幕的40%,在iPad上为屏幕的60%): enter image description here

我使用特征集合来设置iPhone方向的限制条件,并定义每个限制条件要安装在哪个集合中。对于iPhone而言,有wChR(肖像)和wChC(横向)。或者是wC和hAny:

enter image description here

但是对于iPad上的纵向和横向方向,只使用单个特征集合(wRhR),因此iPhone使用的方式不适用。为了更改这些情况下的约束条件,我创建了两个约束集(第一个用于iPad横向,第二个用于iPad纵向):

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

注意: 1. 在Storyboard中选择几个所需的约束条件,并将它们与您的.m文件连接起来。要查看添加到数组中的约束条件,请单击.m文件中属性左侧的“+”按钮: enter image description here 2. 我使用约束优先级解决iPad上的约束冲突。
最后,我实现了configConstraints方法,根据iPad的方向切换约束集,并重写了viewWillTransitionToSize方法:
- (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];
    }
}

也许在加载或显示视图的其他位置需要调用configConstraints方法,但基本思想已经描述完毕。

我们能否仅使用Storyboard完成编程部分? - Satish Mavani

4

使用自动布局或少量代码可以完成吗?

对于iPad,您需要两者都使用。

  1. 为每个视图定义布局约束,不要为这些视图设置宽度或高度约束。
  2. 在视图一和二上连接IBOutlets的每个约束。
  3. 在您的视图控制器中实现UIContentContainer协议

    viewWillTransitionToSize(_ size: CGSize,withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator)

讨论 UIKit在改变所呈现视图控制器的视图大小之前调用此方法。您可以在自己的对象中覆盖此方法,并使用它来执行与大小更改相关的其他任务。例如,容器视图控制器可能会使用此方法来覆盖其嵌入式子视图控制器的特征。使用提供的协调器对象来动画显示所做的任何更改。

如果您在自定义视图控制器中覆盖此方法,请始终在您的实现中某个位置调用super,以便UIKit可以适当地转发大小更改消息。视图控制器将大小更改消息转发到其视图和子视图控制器。呈现控制器将大小更改转发给其呈现的视图控制器。

是您需要实现的方法。在此方法中,您需要检查大小的属性宽度和高度,以确定布局应如何更改-即横向或纵向布局。请注意,此方法表示它更改为传入的大小。

  1. 根据设备是否旋转到纵向或横向调整约束。

4

将这两个视图放入堆栈视图中,通过更改堆栈视图的轴方向来实现更简单的操作。

  1. 创建一个指向堆栈视图的IBOulet引用
  2. 实现viewWillTransitionToSize方法
  3. 通过self.stackView.axis = .vertical或.horizontal为每个方向更改轴

1
确实,这里有一个关于那个特定解决方案的不错教程 https://www.natashatherobot.com/magical-view-rotation-with-stackview/。然而它并没有挽救苹果在iPad上使大小类别相同的基本愚蠢。 - Fattie

3

17
也许有人可以解释一下这个回答如何回答了问题。阅读教程并下载示例后,两个顶层视图在 iPhone 布局中会像问题中一样改变位置,但在 iPad 上不会。这正是问题所在,尺寸类/特征在 iPad 竖屏和 iPad 横屏上是相同的。也许我漏掉了什么…… - InfalibleCoinage
这是一个具有挑战性的话题,简而言之,当您将项目升级为使用通用故事板/自适应布局时,您将拥有一个适用于所有设备的单个故事板(因此在XCode中的项目/目标/常规选项卡中列出了一个“主界面”,而不是两个)。我一直在通过这里的视频和教程努力寻找额外的帮助:https://developer.apple.com/design/adaptivity/ - Matt
10
确实,一个单一的故事板/ xib 是正确的方式。然而,苹果不区分 iPad 竖屏和横屏的尺寸类别/特征。您的答案表明这在 iOS 11 中已经改变,但事实并非如此,仍需要使用各种解决方法来实现此行为。 - InfalibleCoinage

0

我唯一轻松实现它在iPad和iPhone上工作的方法是通过编程方式。这是使用Swift 5.0在Xcode 10.2中完成的。

在您的ViewController中,定义您想根据方向更改的两个视图:

@IBOutlet weak var raceInfoView: UIStackView!
@IBOutlet weak var raceListView: UITableView!

然后在你的故事板中定义那些始终保持不变的约束条件,并定义那些在你的ViewController中将要更改的约束条件。

private var portraitRaceInfoViewTrailing: NSLayoutConstraint!
private var portraitRaceInfoViewBottom: NSLayoutConstraint!
private var portraitRaceListViewLeading: NSLayoutConstraint!
private var landscapeRaceInfoViewTrailing: NSLayoutConstraint!
private var landscapeRaceInfoViewBottom: NSLayoutConstraint!
private var landscapeRaceListViewTop: NSLayoutConstraint!

接下来,初始化约束条件,我将其放在viewDidLoad中,但可能还可以放在其他地方。
override func viewDidLoad() {
    super.viewDidLoad()

    portraitRaceInfoViewTrailing = NSLayoutConstraint(
        item: racesView as Any, attribute: NSLayoutConstraint.Attribute.trailing,
        relatedBy: NSLayoutConstraint.Relation.equal,
        toItem: raceInfoView, attribute: NSLayoutConstraint.Attribute.trailing,
        multiplier: 1, constant: 0)
    portraitRaceInfoViewBottom = NSLayoutConstraint(
        item: raceListView as Any, attribute: NSLayoutConstraint.Attribute.top,
        relatedBy: NSLayoutConstraint.Relation.equal,
        toItem: raceInfoView, attribute: NSLayoutConstraint.Attribute.bottom,
        multiplier: 1, constant: 0)
    portraitRaceListViewLeading = NSLayoutConstraint(
        item: raceListView as Any, attribute: NSLayoutConstraint.Attribute.leading,
        relatedBy: NSLayoutConstraint.Relation.equal,
        toItem: racesView, attribute: NSLayoutConstraint.Attribute.leading,
        multiplier: 1, constant: 0)

    landscapeRaceInfoViewTrailing = NSLayoutConstraint(
        item: raceListView as Any, attribute: NSLayoutConstraint.Attribute.leading,
        relatedBy: NSLayoutConstraint.Relation.equal,
        toItem: raceInfoView, attribute: NSLayoutConstraint.Attribute.trailing,
        multiplier: 1, constant: 0)
    landscapeRaceInfoViewBottom = NSLayoutConstraint(
        item: raceInfoView as Any, attribute: NSLayoutConstraint.Attribute.bottom,
        relatedBy: NSLayoutConstraint.Relation.equal,
        toItem: racesView, attribute: NSLayoutConstraint.Attribute.bottom,
        multiplier: 1, constant: 0)
    landscapeRaceListViewTop = NSLayoutConstraint(
        item: raceListView as Any, attribute: NSLayoutConstraint.Attribute.top,
        relatedBy: NSLayoutConstraint.Relation.equal,
        toItem: racesView, attribute: NSLayoutConstraint.Attribute.top,
        multiplier: 1, constant: 0)

    applyOrientationConstraints()
}

在程序中编程声明约束看起来有点可怕,但实际上非常容易。您可以在故事板中创建约束并查看所有值,然后将正确的值复制到代码中的正确位置。

最后,在viewDidLoad中使用applyOrientationConstraints()应用约束。

func applyOrientationConstraints() {
    let orient = UIApplication.shared.statusBarOrientation
    switch orient {
    case .portrait:
        NSLayoutConstraint.activate([portraitRaceInfoViewTrailing, portraitRaceInfoViewBottom, portraitRaceListViewLeading])
        NSLayoutConstraint.deactivate([landscapeRaceInfoViewTrailing, landscapeRaceInfoViewBottom, landscapeRaceListViewTop])
        break
    default:
        NSLayoutConstraint.deactivate([portraitRaceInfoViewTrailing, portraitRaceInfoViewBottom, portraitRaceListViewLeading])
        NSLayoutConstraint.activate([landscapeRaceInfoViewTrailing, landscapeRaceInfoViewBottom, landscapeRaceListViewTop])
        break
    }
}

最后,重写viewWillTransition方法,在方向改变时应用约束。
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    coordinator.animate(alongsideTransition: { (UIViewControllerTransitionCoordinatorContext) -> Void in
        self.applyOrientationConstraints()
    }, completion: { (UIViewControllerTransitionCoordinatorContext) -> Void in
        print("rotation completed")
    })
    super.viewWillTransition(to: size, with: coordinator)
}

-1

个人意见.. Swift 5:

(请连接插座....)

//
//  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)
    }
}

IN SIMULATOR.......


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接