Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS constraints doesn't allow to use multiplier

I am trying to layout some custom views and when I try to activate the constraints, Xcode says that I can't use multiplier. Here is an example of the code:

class MenuView: UIView {

    var addButton: AddButton!
    var settingsButton: SettingsButton!

    // ........

    func setConstraints (withBarReference reference: NSLayoutYAxisAnchor) {
        NSLayoutConstraints.activateConstraints([
             // ........
             addButton.centerXAnchor.constraintEqualToAnchor(self.centerXAnchor, multiplier: 0.5),
             // ........
             settingsButton.centerXAnchor.constraintEqualToAnchor(self.centerXAnchor, multiplier: 1.5)
        ])
    }

}

The thing here is that Xcode gives a syntax error on the contraintEqualToAnchor: functions and says that I should replace "multiplier" to "constant".

Why can't I use the multiplier option with the X center anchors?

like image 838
Jaime_mc2 Avatar asked Aug 05 '16 12:08

Jaime_mc2


4 Answers

You can't use multipliers on NSLayoutXAxisAnchor anchors - multiplying by a position along a line doesn't make sense in a way that the constraints system can understand. You can only use multipliers with NSLayoutDimension anchors, which measure lengths, like the width.

The layout you are trying to make would be better achieved using a stack view.

like image 187
jrturton Avatar answered Nov 06 '22 04:11

jrturton


You can't set multiplier using helper functions, but you can set multiplier using NSLayoutConstraint initializer. Just got stuck by this myself, but found the answer.

Your code: addButton.centerXAnchor.constraintEqualToAnchor(self.centerXAnchor, multiplier: 0.5)

Correct code: NSLayoutConstraint(item: addButton, attribute: .centerX, relatedBy: .equal, toItem: self, attribute: .centerX, multiplier: 0.5, constant: 0)

Also, don't forget to activate this constraint by typing isActive = true

like image 38
Raimundas Sakalauskas Avatar answered Nov 06 '22 03:11

Raimundas Sakalauskas


Previous answers work very weird now.

You can simply create UILayoutGuide with multiplier width/height with view and set guide.trailing equal to the centerX of your subview.

For example, if you need to place the addButton in the first 1/3 of a view and settingsButton in 2/3 you can simply set two layout guides

let addButtonGuide = UILayoutGuide()
self.addLayoutGuide(addButtonGuide)
addButtonGuide.widthAnchor.constraint(equalTo: self.widthAnchor, multiplier: 1/3).isActive = true
addButtonGuide.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
addButton.centerXAnchor.constraint(equalTo: addButtonGuide.trailingAnchor).isActive = true

// same for settingsButton but using 2/3 for the multiplier

But the really best way is to use UIStackView and set its distribution property to equalCentering.

Another option is to use uncommon Auto Layout API to create NSLayoutDimension between two centerXAnchors and make constraint to self.widthAnchor:

addButton.centerXAnchor.anchorWithOffset(to: self.centerXAnchor)
    .constraint(equalTo: self.widthAnchor, multiplier: 0.25).isActive = true

self.centerXAnchor.anchorWithOffset(to: settingsButton.centerXAnchor)
    .constraint(equalTo: self.widthAnchor, multiplier: 0.25).isActive = true
like image 40
Roman Filippov Avatar answered Nov 06 '22 03:11

Roman Filippov


It seems that in IB you can use the multiplier option with Center X and obtain the effect you're looking for (set the center of button1 at 1/4 the width of the view it's in, and the center of button2 at 2/3 of the width of the view it's in):
setting the center of a button at 1/4 the width of the view it's in, using the Interface Builder. setting the center of a button at 2/3 the width of the view it's in, in StoryBoard

I tried to use it both in code and in IB, and in code I got the same error as you. Surprisingly, in IB it worked, no errors, no warnings. (I am using Xcode 7, will try it in Xcode 8 to see if it still works).

like image 39
SimSim Avatar answered Nov 06 '22 04:11

SimSim