Note that there are some explanatory texts on larger screens.

plurals
  1. POHow to center a button with a custom width using autolayout constraints?
    primarykey
    data
    text
    <p>Please see the following code:</p> <pre><code>def viewDidLoad super self.view.translatesAutoresizingMaskIntoConstraints = false self.view.backgroundColor = UIColor.whiteColor @start = UIButton.buttonWithType(UIButtonTypeRoundedRect).tap do |el| el.translatesAutoresizingMaskIntoConstraints = false el.setTitle('Start', forState:UIControlStateNormal) el.addTarget(self, action:'toStartController', forControlEvents:UIControlEventTouchUpInside) self.view.addSubview(el) end self.layout_subviews end def layout_subviews metrics = { 'space' =&gt; 8 } views_dict = { 'superview' =&gt; self.view, 'start' =&gt; @start } self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat('H:|-[start(100)]-|', options: NSLayoutFormatAlignAllCenterX, metrics: metrics, views: views_dict)) self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat('V:[start]-|', options: NSLayoutFormatAlignAllBottom, metrics: metrics, views: views_dict)) end </code></pre> <p>The problem I'm having is <code>H:|-[start(100)]-|</code> won't work. What I want is a button with a width of 100 centered on the X-axis and attached to the bottom of the screen with a default margin. As soon as I remove the <code>(100)</code> this works, however the button stretches to the width of the screen minus the default margins. When I specify a custom width I reckon the Auto Layout system can't work out what the left and right margins should be. I get an <code>Unable to simultaneously satisfy constraints.</code> error. I guess this has something to do with the dashes in <code>H:|-[start(100)]-|</code>, which need to have a fluid width to attach the <code>start</code> element to the <code>superview</code>, instead of being the default margins.</p> <p>Any thoughts on how I might solve this?</p> <p><strong>Update (thanks ghettopia):</strong></p> <p><em>This works (notice I'm using a <code>UINavigationController</code> in the app delegate and <code>self.view.translatesAutoresizingMaskIntoConstraints = false</code> in <code>viewDidLoad</code> of <code>TestController</code> is commented out):</em></p> <pre><code>class AppDelegate def application(application, didFinishLaunchingWithOptions:launchOptions) @window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds).tap do |win| controller = TestController.alloc.initWithNibName(nil, bundle:nil) win.rootViewController = UINavigationController.alloc.initWithRootViewController(controller).tap do |root| root.navigationBarHidden = true root.wantsFullScreenLayout = true end win.makeKeyAndVisible end true end end class TestController &lt; UIViewController def viewDidLoad super # self.view.translatesAutoresizingMaskIntoConstraints = false self.view.backgroundColor = UIColor.blueColor @button = UIButton.buttonWithType(UIButtonTypeRoundedRect) @button.translatesAutoresizingMaskIntoConstraints = false self.view.addSubview(@button) views = { 'view' =&gt; self.view, 'button' =&gt; @button } self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat('H:[button(100)]', options: 0, metrics: nil, views: views)) self.view.addConstraint(NSLayoutConstraint.constraintWithItem(@button, attribute: NSLayoutAttributeCenterX, relatedBy: NSLayoutRelationEqual, toItem: self.view, attribute: NSLayoutAttributeCenterX, multiplier: 1, constant: 0)) self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat('V:[button]-|', options: 0, metrics: nil, views: views)) end end </code></pre> <p><img src="https://i.stack.imgur.com/vjZGK.png" alt="Correct screen"></p> <p><em>Great. Now I get a blue screen with a button centered on the X-axis with a default margin to the bottom, just as I intended. However, from what I've read <code>self.view.translatesAutoresizingMaskIntoConstraints = false</code> is required to make Auto Layout work. To make that happen, this works as well (notice I'm not using a <code>UINavigationController</code> this time and <code>self.view.translatesAutoresizingMaskIntoConstraints = false</code> in <code>viewDidLoad</code> of <code>TestController</code> IS being used):</em></p> <pre><code>class AppDelegate def application(application, didFinishLaunchingWithOptions:launchOptions) @window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds).tap do |win| win.rootViewController = TestController.alloc.initWithNibName(nil, bundle:nil) win.makeKeyAndVisible end true end end class TestController &lt; UIViewController def viewDidLoad super self.view.translatesAutoresizingMaskIntoConstraints = false self.view.backgroundColor = UIColor.blueColor @button = UIButton.buttonWithType(UIButtonTypeRoundedRect) @button.translatesAutoresizingMaskIntoConstraints = false self.view.addSubview(@button) views = { 'view' =&gt; self.view, 'button' =&gt; @button } self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat('H:[button(100)]', options: 0, metrics: nil, views: views)) self.view.addConstraint(NSLayoutConstraint.constraintWithItem(@button, attribute: NSLayoutAttributeCenterX, relatedBy: NSLayoutRelationEqual, toItem: self.view, attribute: NSLayoutAttributeCenterX, multiplier: 1, constant: 0)) self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat('V:[button]-|', options: 0, metrics: nil, views: views)) end end </code></pre> <p>But that doesn't seem like a proper solution. I need a <code>UINavigationController</code> to create my app structure. The thing is when I don't use any of the above solutions I get a black screen with a button dead in the middle (on both axis). The views seems to be broken: <img src="https://i.stack.imgur.com/fGgh9.png" alt="Black screen"></p> <p>Thoughts? Should I just remove <code>self.view.translatesAutoresizingMaskIntoConstraints = false</code> and forget about it or is it indeed required? If it is, there must be something wrong with my code.</p> <p><strong>Update 2:</strong></p> <p>Interesting tutorial: <a href="http://ioscreator.com/auto-layout-in-ios-6-adding-constraints-through-code/" rel="nofollow noreferrer">Auto Layout in iOS 6: Adding constraints through code</a>. The author doesn't use <code>self.view.translatesAutoresizingMaskIntoConstraints = false</code> in <code>viewDidLoad</code>, only on subviews.</p> <p><strong>Update 3:</strong></p> <p>I think I may have solved the black screen problem by moving <code>self.view.translatesAutoresizingMaskIntoConstraints = false</code> to the <code>init</code> method instead of <code>viewDidLoad</code>. Not sure why this works though, but the screen looks identical to the screenshot now, just as I intented in the first place. Here's the updated code:</p> <pre><code>class AppDelegate def application(application, didFinishLaunchingWithOptions:launchOptions) @window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds).tap do |win| controller = TestController.alloc.initWithNibName(nil, bundle:nil) win.rootViewController = UINavigationController.alloc.initWithRootViewController(controller).tap do |root| root.navigationBarHidden = true root.wantsFullScreenLayout = true end win.makeKeyAndVisible end true end end class TestController &lt; UIViewController def init self.view.translatesAutoresizingMaskIntoConstraints = false end def viewDidLoad super self.view.backgroundColor = UIColor.blueColor @button = UIButton.buttonWithType(UIButtonTypeRoundedRect) @button.translatesAutoresizingMaskIntoConstraints = false self.view.addSubview(@button) views = { 'view' =&gt; self.view, 'button' =&gt; @button } self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat('H:[button(100)]', options: 0, metrics: nil, views: views)) self.view.addConstraint(NSLayoutConstraint.constraintWithItem(@button, attribute: NSLayoutAttributeCenterX, relatedBy: NSLayoutRelationEqual, toItem: self.view, attribute: NSLayoutAttributeCenterX, multiplier: 1, constant: 0)) self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat('V:[button]-|', options: 0, metrics: nil, views: views)) end end </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload