gpt4 book ai didi

ios - stackView 的轴更改导致布局错误

转载 作者:行者123 更新时间:2023-12-01 18:36:57 37 4
gpt4 key购买 nike

我有一个 UIStackView这是根据其宽度改变轴。它包括两个UView仅限s。有一个非常简单的设置(可以复制/粘贴到默认的 Xcode 项目):

class ViewController: UIViewController {

enum DisplayMode {
case regular
case compact
}

private let stackView = UIStackView(frame: .zero)
private let firstView = UIView(frame: .zero)
private let secondView = UIView(frame: .zero)
private var firstViewWidth: NSLayoutConstraint?
private var secondViewWidth: NSLayoutConstraint?

override func viewDidLoad() {
super.viewDidLoad()

stackView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(stackView)
NSLayoutConstraint.activate([
stackView.topAnchor.constraint(equalTo: view.topAnchor),
stackView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
stackView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
])

firstView.backgroundColor = .red
stackView.addArrangedSubview(firstView)
firstView.heightAnchor.constraint(equalToConstant: 80).isActive = true
firstViewWidth = firstView.widthAnchor.constraint(equalTo: stackView.widthAnchor, multiplier: 1/3)
firstViewWidth?.isActive = true

secondView.backgroundColor = .black
stackView.addArrangedSubview(secondView)
secondView.heightAnchor.constraint(equalToConstant: 80).isActive = true
secondViewWidth = secondView.widthAnchor.constraint(equalTo: stackView.widthAnchor, multiplier: 2/3)
secondViewWidth?.isActive = true
}

override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if view.bounds.width < 400 {
switchMode(.compact)
} else {
switchMode(.regular)
}
}
}

private extension ViewController {

func switchMode(_ mode: DisplayMode) {
switch mode {
case .regular:
stackView.axis = .horizontal
firstViewWidth?.isActive = true
secondViewWidth?.isActive = true
case .compact:
stackView.axis = .vertical
firstViewWidth?.isActive = false
secondViewWidth?.isActive = false
}
}
}

它工作得很好,但它给了我无意义的布局错误(输出中的所有约束似乎都很好),同时从紧凑更改为常规:
(
"<NSLayoutConstraint:0x6000002c1c20 UIView:0x7fbd4dc149a0.width == 0.333333*UIStackView:0x7fbd4df02430.width (active)>",
"<NSLayoutConstraint:0x6000002c2170 UIView:0x7fbd4dc14d90.width == 0.666667*UIStackView:0x7fbd4df02430.width (active)>",
"<NSLayoutConstraint:0x6000002f2080 'UISV-canvas-connection' UIStackView:0x7fbd4df02430.leading == UIView:0x7fbd4dc149a0.leading (active)>",
"<NSLayoutConstraint:0x6000002f1c70 'UISV-canvas-connection' H:[UIView:0x7fbd4dc14d90]-(0)-| (active, names: '|':UIStackView:0x7fbd4df02430 )>",
"<NSLayoutConstraint:0x6000002f05f0 'UISV-spacing' H:[UIView:0x7fbd4dc149a0]-(0)-[UIView:0x7fbd4dc14d90] (active)>"
)

有人可以解释为什么会这样吗?动态轴是罪魁祸首吗?

最佳答案

首先,viewDidLayoutSubviews 不是处理方向变化的好选择。Apple 推荐的方法是 viewWillTransitionToSize。
更多详情:What is the "right" way to handle orientation changes in iOS 8?

当您第一次运行代码时,堆栈 View 出现垂直分布,第一个 View 和第二个 View 的情况都具有以下约束

第一 View ->

         Leading =  StackView Leading,
Trailing = StackView Trailing,
Top = StackView Top,
height = 80

第二 View ->
            Leading =  StackView Leading    ,
Top = FirstView Top,
Trailing = StackView Trailing,
height = 80

当您将设备从纵向旋转到横向时,堆栈 View 会出现水平分布并使跟随约束处于事件状态。

FirstView.Width = StackView.Width * 1/3

导致 FirstView 与您以前的约束冲突(StackView 前导,StackView 尾随)。因为现在您有两个宽度约束
  • (FirstView.leading = StackView 领先 & FirstView.trailing = StackView 尾随) == (FirstView 宽度 == StackView.width)
  • FirstView.Width = StackView.Width * 1/3

  • 为什么 StackView 不自动删除冲突约束之一?

    --> 因为这两个约束都具有高优先级(1000)。如果我们只是将 firstViewWidth 更改为更低(999)并删除 secondViewWidth 约束,那么您的解决方案将起作用

    尝试用以下代码替换您的代码
       import UIKit

    class ViewController: UIViewController {

    enum DisplayMode {
    case regular
    case compact
    }

    private let stackView = UIStackView(frame: .zero)
    private let firstView = UIView(frame: .zero)
    private let secondView = UIView(frame: .zero)
    private var firstViewWidth: NSLayoutConstraint?
    private var secondViewWidth: NSLayoutConstraint?

    override func viewDidLoad() {
    super.viewDidLoad()

    stackView.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(stackView)
    NSLayoutConstraint.activate([
    stackView.topAnchor.constraint(equalTo: view.topAnchor),
    stackView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
    stackView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
    ])

    firstView.backgroundColor = .red
    stackView.addArrangedSubview(firstView)
    firstView.heightAnchor.constraint(equalToConstant: 80).isActive = true
    firstViewWidth = firstView.widthAnchor.constraint(equalTo: stackView.widthAnchor, multiplier: 1/3)
    firstViewWidth?.priority = UILayoutPriority(rawValue: 999)
    firstViewWidth?.isActive = true

    secondView.backgroundColor = .black
    stackView.addArrangedSubview(secondView)
    secondView.heightAnchor.constraint(equalToConstant: 80).isActive = true


    if self.view.bounds.width < 400 {
    self.switchMode(.compact)
    } else {
    self.switchMode(.regular)
    }
    }

    override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    }

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


    coordinator.animate(alongsideTransition: { (context) in

    }) { (context) in
    if self.view.bounds.width < 400 {
    self.switchMode(.compact)
    } else {
    self.switchMode(.regular)
    }
    }

    }

    }

    private extension ViewController {

    func switchMode(_ mode: DisplayMode) {
    switch mode {
    case .regular:
    stackView.axis = .horizontal
    firstViewWidth?.isActive = true

    case .compact:
    stackView.axis = .vertical
    firstViewWidth?.isActive = false
    }
    }
    }

    关于ios - stackView 的轴更改导致布局错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53125720/

    37 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com