约束条件不能正常运作

时间:2017-05-23 02:05:22

标签: ios xcode swift3 constraints

我目前正在开展一个项目,并且我已经以编程方式创建了一个自定义视图。

以下是我在自定义类中编写的代码:

class CodeView: UIView {

let codeTextView = UITextView()
let nameLabel = UILabel()
let dateLabel = UILabel()
let mainStackView = UIStackView()
let labelStackView = UIStackView()
let buttonStackView = UIStackView()
let lowerStackView = UIStackView()
let copyButton = UIButton()
let shareButton = UIButton()

let size = CGRect(x: 0, y: 0, width: 250, height: 175)

public init(name: String?, date: String?, code: String) {

    if let name = name {
        nameLabel.text = name
    } else {
        nameLabel.isHidden = true
    }

    if let date = date {
        dateLabel.text = date
    } else {
        dateLabel.isHidden = true
    }

    codeTextView.text = code

    super.init(frame: CGRect(x: 0, y: 0, width: 250, height: 175))

    subview()
    setup()
    addingConstraints()

}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}

func setup() {

    self.layer.cornerRadius = 15
    self.backgroundColor = .white

    codeTextView.textColor = .white
    codeTextView.backgroundColor = UIColor(red: 2/255, green: 11/255, blue: 57/255, alpha: 0.75)
    codeTextView.layer.cornerRadius = 15
    codeTextView.font = UIFont(name: "Avenir-Medium", size: 15)

    nameLabel.font = UIFont(name: "Avenir-Medium", size: 17)

    dateLabel.font = UIFont(name: "Avenir-Light", size: 17)

    copyButton.setImage(UIImage(named: "Copy"), for: .normal)
    copyButton.setImage(UIImage(named: "Copy Highlighted"), for: .highlighted)
    copyButton.setImage(UIImage(named: "Copy Highlighted"), for: .selected)
    copyButton.addTarget(self, action: #selector(copyText), for: .touchUpInside)
    copyButton.setTitle("", for: .normal)
    copyButton.imageView?.contentMode = .scaleAspectFit

    shareButton.setImage(UIImage(named: "Share"), for: .normal)
    shareButton.setImage(UIImage(named: "Share Highlighted"), for: .highlighted)
    shareButton.setImage(UIImage(named: "Share Highlighted"), for: .selected)
    shareButton.addTarget(self, action: #selector(shareText), for: .touchUpInside)
    shareButton.setTitle("", for: .normal)
    shareButton.imageView?.contentMode = .scaleAspectFit


    mainStackView.axis = .vertical
    mainStackView.spacing = 10

    lowerStackView.axis = .horizontal
    lowerStackView.alignment = .center
    lowerStackView.distribution = .fillProportionally

    labelStackView.axis = .vertical

    buttonStackView.axis = .horizontal
    buttonStackView.alignment = .fill
    buttonStackView.distribution = .fillEqually
    buttonStackView.spacing = 10

}

func addingConstraints() {

    //TranslatesAutoresizingMaskIntoConstraints = false
    self.translatesAutoresizingMaskIntoConstraints = false
    codeTextView.translatesAutoresizingMaskIntoConstraints = false
    mainStackView.translatesAutoresizingMaskIntoConstraints = false
    labelStackView.translatesAutoresizingMaskIntoConstraints = false
    buttonStackView.translatesAutoresizingMaskIntoConstraints = false
    nameLabel.translatesAutoresizingMaskIntoConstraints = false
    dateLabel.translatesAutoresizingMaskIntoConstraints = false
    copyButton.translatesAutoresizingMaskIntoConstraints = false
    shareButton.translatesAutoresizingMaskIntoConstraints = false

    var constraint = [NSLayoutConstraint]()

    let ViewWidth = NSLayoutConstraint(item: self, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .width, multiplier: 1, constant: 250)
    let ViewHeight = NSLayoutConstraint(item: self, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .height, multiplier: 1, constant: 175)

    let MainStackViewCenterX = NSLayoutConstraint(item: mainStackView, attribute: .centerX, relatedBy: .equal, toItem: self, attribute: .centerX, multiplier: 1, constant: 0)
    let MainStackViewCenterY = NSLayoutConstraint(item: mainStackView, attribute: .centerY, relatedBy: .equal, toItem: self, attribute: .centerY, multiplier: 1, constant: 0)
    let MainStackViewTop = NSLayoutConstraint(item: mainStackView, attribute: .top, relatedBy: .equal, toItem: self, attribute: .topMargin, multiplier: 1, constant: 5)
    let MainStackViewLeft = NSLayoutConstraint(item: mainStackView, attribute: .leading, relatedBy: .equal, toItem: self, attribute: .leadingMargin, multiplier: 1, constant: 5)
    let MainStackViewRight = NSLayoutConstraint(item: mainStackView, attribute: .trailing, relatedBy: .equal, toItem: self, attribute: .trailingMargin, multiplier: 1, constant: 5)

    let CodeTextViewTop = NSLayoutConstraint(item: codeTextView, attribute: .top, relatedBy: .equal, toItem: mainStackView, attribute: .topMargin, multiplier: 1, constant: 0)
    let CodeTextViewLeft = NSLayoutConstraint(item: codeTextView, attribute: .leading, relatedBy: .equal, toItem: mainStackView, attribute: .leadingMargin, multiplier: 1, constant: 0)
    let CodeTextViewRight = NSLayoutConstraint(item: codeTextView, attribute: .trailing, relatedBy: .equal, toItem: mainStackView, attribute: .trailingMargin, multiplier: 1, constant: 0)

    let LowerStackViewBottom = NSLayoutConstraint(item: lowerStackView, attribute: .bottom, relatedBy: .equal, toItem: mainStackView, attribute: .bottomMargin, multiplier: 1, constant: 0)
    let LowerStackViewLeft = NSLayoutConstraint(item: lowerStackView, attribute: .leading, relatedBy: .equal, toItem: mainStackView, attribute: .leadingMargin, multiplier: 1, constant: 0)
    let LowerStackViewRight = NSLayoutConstraint(item: lowerStackView, attribute: .trailing, relatedBy: .equal, toItem: mainStackView, attribute: .trailingMargin, multiplier: 1, constant: 0)

    let LabelStackViewCenterY = NSLayoutConstraint(item: labelStackView, attribute: .centerY, relatedBy: .equal, toItem: lowerStackView, attribute: .centerY, multiplier: 1, constant: 0)
    let LabelStackViewLeft = NSLayoutConstraint(item: labelStackView, attribute: .leading, relatedBy: .equal, toItem: lowerStackView, attribute: .leadingMargin, multiplier: 1, constant: 0)

    let ButtonStackViewCenterY = NSLayoutConstraint(item: buttonStackView, attribute: .centerY, relatedBy: .equal, toItem: lowerStackView, attribute: .centerY, multiplier: 1, constant: 0)
    let ButtonStackViewRight = NSLayoutConstraint(item: buttonStackView, attribute: .trailing, relatedBy: .equal, toItem: lowerStackView, attribute: .trailingMargin, multiplier: 1, constant: 0)

    let CopyButtonWidth = NSLayoutConstraint(item: copyButton, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .width, multiplier: 1, constant: 28)
    let CopyButtonHeight = NSLayoutConstraint(item: copyButton, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .height, multiplier: 1, constant: 35)

    constraint.append(contentsOf: [ViewHeight, ViewWidth, MainStackViewCenterX, MainStackViewCenterY, MainStackViewTop, MainStackViewLeft, MainStackViewRight, CodeTextViewTop, CodeTextViewLeft, CodeTextViewRight, LowerStackViewBottom, LowerStackViewLeft, LowerStackViewRight, LabelStackViewCenterY, LabelStackViewLeft, ButtonStackViewCenterY, ButtonStackViewRight, CopyButtonWidth, CopyButtonHeight])

    NSLayoutConstraint.activate(constraint)

}

func subview() {

    self.addSubview(codeTextView)
    self.addSubview(nameLabel)
    self.addSubview(dateLabel)
    self.addSubview(copyButton)
    self.addSubview(shareButton)
    self.addSubview(mainStackView)
    self.addSubview(lowerStackView)
    self.addSubview(labelStackView)
    self.addSubview(buttonStackView)

    mainStackView.addArrangedSubview(codeTextView)
    mainStackView.addArrangedSubview(lowerStackView)

    lowerStackView.addArrangedSubview(labelStackView)
    lowerStackView.addArrangedSubview(buttonStackView)

    labelStackView.addArrangedSubview(nameLabel)
    labelStackView.addArrangedSubview(dateLabel)

    buttonStackView.addArrangedSubview(copyButton)
    buttonStackView.addArrangedSubview(shareButton)

}



func copyText() {
    UIPasteboard.general.string = codeTextView.text
}

func shareText() {
    let alert = UIAlertController(title: "Share?", message: "You probably don't want to share your code to everyone out there", preferredStyle: .alert)
    alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
    alert.addAction(UIAlertAction(title: "Share", style: .default, handler: { (action) in
        let activity = UIActivityViewController(activityItems: [self.codeTextView.text], applicationActivities: nil)
        UIApplication.shared.keyWindow?.rootViewController?.present(activity, animated: true, completion: nil)
    }))
    UIApplication.shared.keyWindow?.rootViewController?.present(alert, animated: true, completion: nil)
}
}

这是我在想要将视图添加到应用程序时编写的代码:

@IBOutlet weak var contentView: UIView!
let codeView1 = CodeView(name: "Hello", date: "Today", code: "Bla bla bla")
let stackView = UIStackView()
var viewArray = [CodeView]()

override func viewDidLoad() {
    super.viewDidLoad()

    viewArray.append(codeView1)

    for i in viewArray {
        stackView.addArrangedSubview(i)
    }

    contentView.addSubview(stackView)

    stackView.translatesAutoresizingMaskIntoConstraints = false

    stackView.axis = .horizontal
    stackView.alignment = .center
    stackView.spacing = 20

    let centerX = NSLayoutConstraint(item: stackView, attribute: .centerX, relatedBy: .equal, toItem: contentView, attribute: .centerX, multiplier: 1, constant: 0)
    let centerY = NSLayoutConstraint(item: stackView, attribute: .centerY, relatedBy: .equal, toItem: contentView, attribute: .centerY, multiplier: 1, constant: 0)

    NSLayoutConstraint.activate([centerX, centerY])

}

但在运行应用后,它看起来像this

即使我希望它看起来像this

我在代码中添加了与故事板中使用的完全相同的约束。

非常感谢,非常感谢各种帮助

1 个答案:

答案 0 :(得分:0)

以编程方式编码约束时,通常最好使用iOS 9约束锚点。这是我用于以编程方式开发的聊天应用中的用户单元格的约束锚点代码片段。

    //ios 9 constraint anchors
    //need x,y,width,height anchors
    profileImageView.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 8).isActive = true
    profileImageView.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true
    profileImageView.widthAnchor.constraint(equalToConstant: 48).isActive = true
    profileImageView.heightAnchor.constraint(equalToConstant: 48).isActive = true

    //need x,y,width,height anchors
    timeLabel.rightAnchor.constraint(equalTo: self.rightAnchor).isActive = true
    timeLabel.topAnchor.constraint(equalTo: self.topAnchor, constant: 18).isActive = true
    timeLabel.widthAnchor.constraint(equalToConstant: 100).isActive = true
    timeLabel.heightAnchor.constraint(equalTo: textLabel!.heightAnchor).isActive = true
}

显然,您的约束的详细信息会与此示例不同,但这应该为您提供一个模板供您进行试验,以便解决您的问题。