swift 如何以编程方式设置自动布局

swift how to set autolayout programmatically

我在一个视图中有按钮,在肖像模式下我想要这样 -

这是通过以下代码实现的-

//original potrait mode/////

 import UIKit
 class PotraitViewController: UIViewController {
 override func viewDidLoad() {
 let buttonred = UIButton()
 buttonred.backgroundColor = UIColor.red
 let buttonblue = UIButton()
 buttonblue.backgroundColor = UIColor.blue
 let landscapesmallview = UIView()
 view.addSubview(landscapesmallview)
 landscapesmallview.addSubview(buttonred)
 landscapesmallview.addSubview(buttonblue)
 buttonred.translatesAutoresizingMaskIntoConstraints = false
 buttonblue.translatesAutoresizingMaskIntoConstraints = false
 NSLayoutConstraint.activate([

    buttonred.topAnchor.constraint(equalTo: view.topAnchor,constant: 200),
    buttonred.centerXAnchor.constraint(equalTo: view.centerXAnchor),
    buttonred.trailingAnchor.constraint(equalTo: view.trailingAnchor,constant:-20),
    buttonred.widthAnchor.constraint(equalToConstant: 50),
    //-------
    buttonblue.topAnchor.constraint(equalTo: buttonred.bottomAnchor,constant: 40),
    buttonblue.leadingAnchor.constraint(equalTo: buttonred.leadingAnchor),
    buttonblue.trailingAnchor.constraint(equalTo:buttonred.trailingAnchor),
    buttonblue.widthAnchor.constraint(equalTo: buttonred.widthAnchor)

      ])
    }
  }

在横向模式下我想要这样 -

这是通过以下代码实现的-

 // original lanscape mode/////

import UIKit
class LandscapeViewController: UIViewController {
override func viewDidLoad() {
let buttonred = UIButton()
buttonred.backgroundColor = UIColor.red
let buttonblue = UIButton()
buttonblue.backgroundColor = UIColor.blue
view.addSubview(buttonred)
view.addSubview(buttonblue)
buttonred.translatesAutoresizingMaskIntoConstraints = false
buttonblue.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([

    buttonred.centerYAnchor.constraint(equalTo: view.centerYAnchor),
    buttonred.leadingAnchor.constraint(equalTo: view.leadingAnchor,constant:40),
    buttonred.trailingAnchor.constraint(equalTo: view.centerXAnchor,constant:-20),
    buttonred.widthAnchor.constraint(equalToConstant: 50),

    //-------
    buttonblue.centerYAnchor.constraint(equalTo: buttonred.centerYAnchor),
    buttonblue.leadingAnchor.constraint(equalTo: view.centerXAnchor,constant:40),
    buttonblue.trailingAnchor.constraint(equalTo: view.trailingAnchor,constant:-20),
    buttonblue.widthAnchor.constraint(equalTo:buttonred.widthAnchor)

       ])
     }
  }

因此,我尝试使用以下代码通过屏幕旋转来实现,即借助以下代码以编程方式实现纵向和横向视图中的两种不同布局:-

import UIKit

class NewViewController: UIViewController {
override func viewDidLoad() {
let buttonredlandscape = UIButton()
buttonredlandscape.backgroundColor = UIColor.red
let buttonbluelandscape = UIButton()
buttonbluelandscape.backgroundColor = UIColor.blue
let buttonredportrait = UIButton()
buttonredportrait.backgroundColor = UIColor.red
let buttonblueportrait = UIButton()
buttonblueportrait.backgroundColor = UIColor.blue

let landscapesmallview = UIView()
let portraitsmallview = UIView()
landscapesmallview.backgroundColor = UIColor.gray
portraitsmallview.backgroundColor = UIColor.purple
landscapesmallview.frame = view.frame
portraitsmallview.frame = view.frame
view.addSubview(landscapesmallview)
view.addSubview(portraitsmallview)


landscapesmallview.addSubview(buttonredlandscape)
landscapesmallview.addSubview(buttonbluelandscape)
portraitsmallview.addSubview(buttonredportrait)
portraitsmallview.addSubview(buttonblueportrait)
buttonredlandscape.translatesAutoresizingMaskIntoConstraints = false
buttonbluelandscape.translatesAutoresizingMaskIntoConstraints = false
buttonredportrait.translatesAutoresizingMaskIntoConstraints = false
buttonblueportrait.translatesAutoresizingMaskIntoConstraints = false

NSLayoutConstraint.activate([

     buttonredlandscape.centerYAnchor.constraint(equalTo:landscapesmallview.centerYAnchor),
      buttonredlandscape.topAnchor.constraint(equalTo:landscapesmallview.topAnchor,constant:40),
    buttonredlandscape.trailingAnchor.constraint(equalTo:   landscapesmallview.centerXAnchor,constant:-20),
    buttonredlandscape.heightAnchor.constraint(equalTo:   landscapesmallview.heightAnchor,constant:50),

    buttonbluelandscape.centerYAnchor.constraint(equalTo:buttonredlandscape.centerYAnchor),
    buttonbluelandscape.leadingAnchor.constraint(equalTo: landscapesmallview.centerXAnchor,constant:40),
    buttonbluelandscape.trailingAnchor.constraint(equalTo: landscapesmallview.trailingAnchor,constant:-20),
    buttonbluelandscape.heightAnchor.constraint(equalTo: buttonredlandscape.heightAnchor),


    buttonredportrait.topAnchor.constraint(equalTo: portraitsmallview.topAnchor,constant: 200),
    buttonredportrait.centerXAnchor.constraint(equalTo: portraitsmallview.centerXAnchor),
    buttonredportrait.trailingAnchor.constraint(equalTo: portraitsmallview.trailingAnchor,constant:-20),
    buttonredportrait.widthAnchor.constraint(equalTo: buttonredportrait.widthAnchor),

    buttonblueportrait.topAnchor.constraint(equalTo: buttonredportrait.bottomAnchor,constant: 40),
    buttonblueportrait.leadingAnchor.constraint(equalTo: buttonredportrait.leadingAnchor),
    buttonblueportrait.trailingAnchor.constraint(equalTo:buttonredportrait.trailingAnchor),
    buttonblueportrait.widthAnchor.constraint(equalTo: buttonredportrait.widthAnchor)


     ])

//-------



func viewWillTransition(to size: CGSize, with coordinator:    ) {
    if UIDevice.current.orientation.isLandscape {
        landscapesmallview.translatesAutoresizingMaskIntoConstraints = false
        portraitsmallview.translatesAutoresizingMaskIntoConstraints = true
     } else if UIDevice.current.orientation.isPortrait {
        portraitsmallview.translatesAutoresizingMaskIntoConstraints = false
        landscapesmallview.translatesAutoresizingMaskIntoConstraints = true

        }
      }
    }
 }

在肖像模式下显示 -

横向模式显示 -

如何以编程方式实现我想要的,即最上面的 2 个按钮在用户每次旋转设备时以编程方式重新排列它们自己。它不仅仅是按钮。它可以是标签、图像、collectionview 等或任何东西。结果是我想以编程方式在横向和纵向模式下实现两种不同的布局,而不管设备如何。

注意事项:-

i) 我已经尝试将 NSLayoutAnchor 与 "NSLayoutConstraint.activate" 一起使用,因为苹果推荐它,但如果可以使用其他方法(如视觉格式等)使代码更短(更快)。我同意还有/

ii) 如果可能的话,我不想用stackview或者containerview,因为标签、按钮等可以有很多种类,但如果没有别的办法,我会用。

iii) 我的代码是否符合 DRY 原则?

此外,伙计们,我不应该得到负面评价,因为据我所知,以前没有人问过这个问题。请大家不要打负分,鼓励一下。

refer this this image for handling in device orientation

将两个按钮置于堆栈视图中,并使堆栈视图垂直居中,水平居中

有多种方法可以做到这一点。一种方法:

  • 声明两个 "constraint" 数组
    • 一个持有"narrow view"约束
    • 一个持有"wide view"约束
  • 根据需要激活/停用约束

这是一个完整的例子:

class ChangeLayoutViewController: UIViewController {

    let redButton: UIButton = {
        let v = UIButton()
        v.translatesAutoresizingMaskIntoConstraints = false
        v.backgroundColor = .red
        v.setTitle("Red Button", for: [])
        return v
    }()

    let blueButton: UIButton = {
        let v = UIButton()
        v.translatesAutoresizingMaskIntoConstraints = false
        v.backgroundColor = .blue
        v.setTitle("Blue Button", for: [])
        return v
    }()

    var narrowConstraints: [NSLayoutConstraint] = [NSLayoutConstraint]()
    var wideConstraints: [NSLayoutConstraint] = [NSLayoutConstraint]()

    override func viewDidLoad() {
        super.viewDidLoad()

        view.addSubview(redButton)
        view.addSubview(blueButton)

        let g = view.safeAreaLayoutGuide

        var c: NSLayoutConstraint

        // MARK: - narrow orientation

        // constrain redButton above blueButton

        // constrain redButton leading and trailing to safe-area (with 8-pts on each side)
        c = redButton.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 8.0)
        narrowConstraints.append(c)
        c = redButton.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -8.0)
        narrowConstraints.append(c)

        // constrain blueButton leading and trailing to safe-area (with 8-pts on each side)
        c = blueButton.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 8.0)
        narrowConstraints.append(c)
        c = blueButton.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -8.0)
        narrowConstraints.append(c)

        // constrain redButton top 40-pts from safe-area top
        c = redButton.topAnchor.constraint(equalTo: g.topAnchor, constant: 40.0)
        narrowConstraints.append(c)
        // constrain blueButton top 20-pts from redButton bottom
        c = blueButton.topAnchor.constraint(equalTo: redButton.bottomAnchor, constant: 20.0)
        narrowConstraints.append(c)


        // MARK: - wide orientation

        // constrain redButton & blueButton side-by-side
        //  with equal widths and 8-pts between them

        // constrain redButton leading 8-pts from safe-area leading
        c = redButton.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 8.0)
        wideConstraints.append(c)
        // constrain blueButton trailing 8-pts from safe-area trailing
        c = blueButton.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -8.0)
        wideConstraints.append(c)

        // constrain blueButton leading 8-pts from redButton trailing
        c = blueButton.leadingAnchor.constraint(equalTo: redButton.trailingAnchor, constant: 8.0)
        wideConstraints.append(c)

        // constrain buttons to equal widths
        c = blueButton.widthAnchor.constraint(equalTo: redButton.widthAnchor)
        wideConstraints.append(c)

        // constrain both buttons centerY to safe-area centerY
        c = redButton.centerYAnchor.constraint(equalTo: g.centerYAnchor)
        wideConstraints.append(c)
        c = blueButton.centerYAnchor.constraint(equalTo: g.centerYAnchor)
        wideConstraints.append(c)

        // activate initial constraints based on view width:height ratio
        changeConstraints(view.frame.width > view.frame.height)

    }

    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        super.viewWillTransition(to: size, with: coordinator)
        // change active set of constraints based on view width:height ratio
        self.changeConstraints(size.width > size.height)
    }

    func changeConstraints(_ useWide: Bool) -> Void {
        if useWide {
            NSLayoutConstraint.deactivate(narrowConstraints)
            NSLayoutConstraint.activate(wideConstraints)
        } else {
            NSLayoutConstraint.deactivate(wideConstraints)
            NSLayoutConstraint.activate(narrowConstraints)
        }
    }

}

结果: