【问题标题】:Swift: Programmatic Autolayout broken by UNavigationControllerSwift:UNavigationController 破坏了程序化自动布局
【发布时间】:2021-07-14 02:21:21
【问题描述】:

我继承了一个 UIKit 应用程序,我的前任在其中手动编写了所有界面代码。我有一个视图控制器,一个可以正常工作的简单登录屏幕,但是当我将它添加到 UINavigationController 时,它奇怪地被拉伸了。这对我来说没有多大意义。

我觉得我必须缺少一些简单的标志,或者我需要做些什么才能使 Navcontroller 与这个程序化自动布局(希望这是我最后一次)玩得很好

// this a view controller extension    
func apply(constraints: [NSLayoutConstraint]) {
        translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate(constraints)
    }

有我方便的花花公子,看似理智的应用约束的实用程序。例如,让我的密码文本字段看起来不错的漂亮椭圆形小东西设置了这些约束。

// these constraints are being setup in the view controller
        emailCapsuleView.apply(constraints: [
            emailCapsuleView.topAnchor.constraint(equalTo: subBigTitle.bottomAnchor, constant: 24.0),
            emailCapsuleView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            emailCapsuleView.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.8),
            emailCapsuleView.heightAnchor.constraint(equalToConstant: Dimensions.inputFieldHeight)
        ])

在 UINavigationController 之外一切都很好,

但在 UINavigationController 中,一切都超宽且损坏(模拟器拍摄)

这里的宽度不是问题 - 如果我使用一个常数作为宽度,我的子视图仍然偏离中心,尽管它的 centerX 设置为视图控制器的视图的中心 X。

【问题讨论】:

  • 您是否收到任何有关约束冲突的警告? view 是什么?它在导航控制器中报告的宽度是多少?
  • view 是视图控制器的视图。即使宽度是恒定的也没关系。你可以看到一切是如何偏离中心的。
  • 嗯,胶囊的宽度与视图的宽度成正比。在我看来,胶囊的布局“正确”,视野比您想要的要宽,
  • 是的,很明显,与导航控制器中包含的视图控制器通信的宽度是错误的。此外,即使我使用恒定宽度,它仍然偏离中心。
  • 您能否显示以下代码:导航控制器本身以及它的根如何添加到视图中,它可能位于的任何容器视图控制器,以及这个有问题的视图控制器。当然只是相关部分。

标签: ios swift autolayout uikit


【解决方案1】:

配置您的导航控制器,然后像这样尝试:

设置你的对象:

let emailTextfield: UITextField = {
    let tf = UITextField()
    tf.backgroundColor = .white
    tf.layer.borderWidth = 1
    tf.layer.borderColor = UIColor.lightGray.cgColor
    tf.setPadding(left: 10, right: 10)// use my extension below
    tf.attributedPlaceholder = NSAttributedString(string: "Email address", attributes: [.foregroundColor: UIColor.lightGray])
    tf.layer.cornerRadius = 14
    tf.clipsToBounds = true
    tf.translatesAutoresizingMaskIntoConstraints = false
    
    return tf
}()

let passTextfield: UITextField = {
    let tf = UITextField()
    tf.backgroundColor = .white
    tf.layer.borderWidth = 1
    tf.layer.borderColor = UIColor.lightGray.cgColor
    tf.setPadding(left: 10, right: 10)// use my extension below
    tf.attributedPlaceholder = NSAttributedString(string: "Password", attributes: [.foregroundColor: UIColor.lightGray])
    tf.layer.cornerRadius = 14
    tf.clipsToBounds = true
    tf.translatesAutoresizingMaskIntoConstraints = false
    
    return tf
}()

let loginButton: UIButton = {
    let b = UIButton(type: .system)
    b.backgroundColor = .black
    b.setTitle("Save Image", for: .normal)
    b.titleLabel?.font = .systemFont(ofSize: 16, weight: .semibold)
    b.setTitleColor(.white, for: .normal)
    b.layer.cornerRadius = 14
    b.clipsToBounds = true
    b.translatesAutoresizingMaskIntoConstraints = false
    
    return b
}()

let subBigTitle: UILabel = {
    let l = UILabel()
    l.text = "Your Big Title"
    l.font = .systemFont(ofSize: 30, weight: .regular)
    l.textColor = .black
    l.textAlignment = .center
    l.translatesAutoresizingMaskIntoConstraints = false
    return l
}()

现在在 viewDidLoad 中设置 stackView、bigTitle 标签和约束:

view.addSubview(subBigTitle)
    subBigTitle.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
    subBigTitle.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor).isActive = true
    subBigTitle.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor).isActive = true
    subBigTitle.heightAnchor.constraint(equalToConstant: 60).isActive = true
    
    let stackView = UIStackView(arrangedSubviews: [emailTextfield, passTextfield, loginButton])
    stackView.axis = .vertical
    stackView.distribution = .fillEqually
    stackView.spacing = 10
    stackView.translatesAutoresizingMaskIntoConstraints = false
    
    view.addSubview(stackView)
    stackView.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.8).isActive = true
    stackView.heightAnchor.constraint(equalToConstant: 170).isActive = true
    stackView.topAnchor.constraint(equalTo: subBigTitle.bottomAnchor, constant: 24).isActive = true
    stackView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true

要向您的文本字段添加文本填充,请使用我的扩展:

extension UITextField {

func setPadding(left: CGFloat, right: CGFloat){

 let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: left, height: self.frame.size.height))
 self.leftView = paddingView
 self.leftViewMode = .always

 let paddingViewRight = UIView(frame: CGRect(x: 0, y: 0, width: right, height: self.frame.size.height))
 self.rightView = paddingViewRight
 self.rightViewMode = .always
 }
}

结果如下:

【讨论】:

  • 所以,这是继承的代码。我试图避免只是重写整个事情。这家伙也在用他的 Window 做一些奇怪的事情——例如,在我十年的 iOS 开发中,我还没有看到任何人继承 UIWindow。我理解所有这些代码。我基本上都在做这一切。 uinav 控制器或窗口出现问题。我的视图控制器看起来很好,就像你的一样,直到我把它放进这个导航控制器。另外,我的代码对你的约束做了同样的事情。
  • @TomSchulz 您的导航控制器设置正确吗?我为它写了一个扩展stackoverflow.com/a/58361273/5575955 在这个答案的最后部分解释了如何从场景委托中呈现它......看看......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-09-04
  • 2020-11-17
  • 2017-06-13
  • 1970-01-01
  • 2018-03-19
  • 2015-06-23
  • 1970-01-01
相关资源
最近更新 更多