2017-02-13 11 views
1

こんにちは動作しないカスタムに制約を追加するI持って次のコード:だから基本的に私は、幅と高さの制約を持つ2つのボタンを追加している、と私はcancelButtonを設定UIButtonが

class MyController {  
    override func viewDidLoad() { 
     self.addButtons() 

     super.viewDidLoad() 
    } 

    func addButtons() { 
     let cancelButton = UIButton(type: .custom) 
     let validateButton = UIButton(type: .custom) 

     cancelButton.setImage(UIImage(named: "cancel_icon"), for: .normal) 
     validateButton.setImage(UIImage(named: "validate_icon"), for: .normal) 

     cancelButton.addTarget(self, action: #selector(cancelAction), for: .touchUpInside) 
     validateButton.addTarget(self, action: #selector(validateAction), for: .touchUpInside) 

     cancelButton.translatesAutoresizingMaskIntoConstraints = false 
     validateButton.translatesAutoresizingMaskIntoConstraints = false 

     self.view.addSubview(cancelButton) 
     self.view.addSubview(validateButton) 

     let leftCancel = NSLayoutConstraint(item: cancelButton, attribute: .leading, relatedBy: .equal, toItem: self.view, attribute: .leading, multiplier: 1, constant: 16) 
     let bottomCancel = NSLayoutConstraint(item: cancelButton, attribute: .bottom, relatedBy: .equal, toItem: self.view, attribute: .bottom, multiplier: 1, constant: 20) 
     let widthCancel = NSLayoutConstraint(item: cancelButton, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 20) 
     let heightCancel = NSLayoutConstraint(item: cancelButton, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 20) 
     let rightValidate = NSLayoutConstraint(item: validateButton, attribute: .trailing, relatedBy: .equal, toItem: self.view, attribute: .trailing, multiplier: 1, constant: 16) 
     let bottomValidate = NSLayoutConstraint(item: validateButton, attribute: .bottom, relatedBy: .equal, toItem: self.view, attribute: .bottom, multiplier: 1, constant: 20) 
     let widthValidate = NSLayoutConstraint(item: validateButton, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 20) 
     let heightValidate = NSLayoutConstraint(item: validateButton, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 20) 
     NSLayoutConstraint.activate([leftCancel, bottomCancel, rightValidate, bottomValidate, widthCancel, heightCancel, widthValidate, heightValidate]) 

     self.view.layoutIfNeeded() 
    } 

    func cancelAction() { 
     self.dismiss(animated: true, completion: nil) 
    } 

    func validateAction() { 
     self.dismiss(animated: true, completion: nil) 
    } 
} 

左下にはvalidateButtonが表示されます。

マイボタンが表示されません。ボタンのフレームをこのように設定すると、それは機能します:

cancelButton.frame = CGRect(x: 16, y: self.view.frame.height - 40, width: 20, height: 20) 
validateButton.frame = CGRect(x: self.view.frame.width - 36, y: self.view.frame.height - 40, width: 20, height: 20) 

誰かが私の制約に間違いを知っていますか? ありがとう!

+0

私は別の構文を使用しますが、私が見ているものからは2つのことがあります。まず、20x20のボタンはかなり小さいです。多分彼らはレンダリングされています - 確認するbackgroundColorを与えます。次に、両方のボタンが同じ位置に表示されます。しかし、私があなたに言っていることから、あなたがそれらと何をするべきかを知るために、自動レイアウトに十分なものを与えました。 (* .notAnAttribute *が正しくない場合を除き、私は "アンカー"シンタックススタイルを使用し、これを一度も実行しませんでした)EDIT:Doh。私は1つのボタンが先行しているのを見ていないし、もう1つは後ろにいる。私の2番目のコメントを忘れて! – dfd

+1

私はあなたの下限と後続の制約が負であることを望んでいると信じています... – DonMag

答えて

2

はVisualFormatは、その用途がありますが、それはまた、独自の癖がある - そのような要素間の柔軟な間隔とします。ここでVisualFormatのないソリューションです:

//: Playground - noun: a place where people can play 

import UIKit 

import PlaygroundSupport 

class MyController: UIViewController { 
    override func viewDidLoad() { 
     super.viewDidLoad() 

     self.addButtons() 
    } 

    func addButtons() { 
     let cancelButton = UIButton(type: .custom) 
     let validateButton = UIButton(type: .custom) 

     cancelButton.setImage(UIImage(named: "cancel_icon"), for: .normal) 
     validateButton.setImage(UIImage(named: "validate_icon"), for: .normal) 

     cancelButton.addTarget(self, action: #selector(cancelAction), for: .touchUpInside) 
     validateButton.addTarget(self, action: #selector(validateAction), for: .touchUpInside) 

     cancelButton.translatesAutoresizingMaskIntoConstraints = false 
     validateButton.translatesAutoresizingMaskIntoConstraints = false 

     self.view.addSubview(cancelButton) 
     self.view.addSubview(validateButton) 

     validateButton.backgroundColor = UIColor.red 
     cancelButton.backgroundColor = UIColor.blue 

     validateButton.setTitle("V", for: UIControlState()) 
     cancelButton.setTitle("C", for: UIControlState()) 

     let leftCancel = NSLayoutConstraint(item: cancelButton, attribute: .leading, relatedBy: .equal, toItem: self.view, attribute: .leading, multiplier: 1, constant: 16) 
     let bottomCancel = NSLayoutConstraint(item: cancelButton, attribute: .bottom, relatedBy: .equal, toItem: self.view, attribute: .bottom, multiplier: 1, constant: -20) 
     let widthCancel = NSLayoutConstraint(item: cancelButton, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 20) 
     let heightCancel = NSLayoutConstraint(item: cancelButton, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 20) 
     let rightValidate = NSLayoutConstraint(item: validateButton, attribute: .trailing, relatedBy: .equal, toItem: self.view, attribute: .trailing, multiplier: 1, constant: -16) 
     let bottomValidate = NSLayoutConstraint(item: validateButton, attribute: .bottom, relatedBy: .equal, toItem: self.view, attribute: .bottom, multiplier: 1, constant: -20) 
     let widthValidate = NSLayoutConstraint(item: validateButton, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 20) 
     let heightValidate = NSLayoutConstraint(item: validateButton, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 20) 

     NSLayoutConstraint.activate([leftCancel, bottomCancel, rightValidate, bottomValidate, widthCancel, heightCancel, widthValidate, heightValidate]) 

     self.view.layoutIfNeeded() 
    } 

    func cancelAction() { 
     //  self.dismiss(animated: true, completion: nil) 
     print("cancel") 
    } 

    func validateAction() { 
     //  self.dismiss(animated: true, completion: nil) 
     print("validate") 
    } 
} 

var vc = MyController() 
vc.view.backgroundColor = UIColor.green 
vc.view.frame = CGRect(x: 0, y: 0, width: 400, height: 400) 

PlaygroundPage.current.liveView = vc.view 

PlaygroundPage.current.needsIndefiniteExecution = true 

あなたが/結果を確認するために遊び場のページにこれをコピー&ペーストすることができるはずです。私はあなたのボタンイメージを持っていないので、私は "V"と "C"のタイトルを持っています。

重要な違いは、ボトムとトレーリングの値を負に設定することです。つまり、ボタンのボトムを(MINUS 20を含むビューの下に)設定します。同様に、Buttonの後端を含むビューの後端から-16になります。

+0

ありがとう、完璧な、私が間違っていることを見ることができます!負の値は考えていませんでしたが、正の値を持つためには 'item:'と 'toItem:' –

+0

を遊び場に投げて、それを80x80のアイコンを小さな10x10の小さなアイコンに変えてください。 –

1

これは複雑すぎるようです。 VisualFormat文字列で簡単にこれを実現できます。

はこちらをご覧https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/AutolayoutPG/VisualFormatLanguage.html#//apple_ref/doc/uid/TP40010853-CH27-SW1

を持ってここにあなたのコードを使用した例です:

func addButtons() { 
    let cancelButton = UIButton(type: .custom) 
    let validateButton = UIButton(type: .custom) 

    cancelButton.setImage(UIImage(named: "cancel_icon"), for: .normal) 
    validateButton.setImage(UIImage(named: "validate_icon"), for: .normal) 

    cancelButton.addTarget(self, action: #selector(cancelAction), for: .touchUpInside) 
    validateButton.addTarget(self, action: #selector(validateAction), for: .touchUpInside) 

    cancelButton.translatesAutoresizingMaskIntoConstraints = false 
    validateButton.translatesAutoresizingMaskIntoConstraints = false 

    self.view.addSubview(cancelButton) 
    self.view.addSubview(validateButton) 

    // With visual format strings 
    let views = ["cancelButton" : cancelButton, "validateButton" : validateButton] 

    let horizontalFormat = "|[cancelButton]-[validateButton(==cancelButton)]|" 
    let verticalFormat = "V:[cancelButton]-10-|" 

    let horizontalConstraints = NSLayoutConstraint.constraints(withVisualFormat: horizontalFormat, options:.alignAllBottom , metrics: nil, views: views) 
    let verticalConstraints = NSLayoutConstraint.constraints(withVisualFormat: verticalFormat, options:.alignAllBottom, metrics: nil, views: views) 

    NSLayoutConstraint.activate(horizontalConstraints) 
    NSLayoutConstraint.activate(verticalConstraints) 

    self.view.layoutIfNeeded() 
} 
+0

それは私の間違いだったことを理解することができるので、@DonMagの回答を受け入れています!あなたは本当に視覚的なフォーマットに入ることができました。それまで私は避けていたものでした。 –