Ios6 如何使用自动布局约束以自定义宽度将按钮居中?

Ios6 如何使用自动布局约束以自定义宽度将按钮居中?,ios6,autolayout,rubymotion,nslayoutconstraint,visual-format-language,Ios6,Autolayout,Rubymotion,Nslayoutconstraint,Visual Format Language,请参阅以下代码: def viewDidLoad super self.view.translatesAutoresizingMaskIntoConstraints = false self.view.backgroundColor = UIColor.whiteColor @start = UIButton.buttonWithType(UIButtonTypeRoundedRect).tap do |el| el.translatesAutore

请参阅以下代码:

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' => 8 }

    views_dict = { 
      'superview' => self.view, 
      'start' => @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
我遇到的问题是
H:|-[start(100)]-|
不起作用。我想要的是一个宽度为100的按钮,以X轴为中心,并以默认边距连接到屏幕底部。只要我删除
(100)
,这个功能就可以工作,但是按钮会延伸到屏幕的宽度减去默认的边距。当我指定自定义宽度时,我认为自动布局系统无法计算出左右边距应该是多少。我得到一个
无法同时满足约束的错误。
错误。我想这与
H:|-[start(100)]-|
中的破折号有关,它需要有一个流体宽度来将
start
元素附加到
superview
,而不是默认的边距

有没有想过我该如何解决这个问题

更新(感谢贫民区):

这是可行的(注意,我在应用程序委托中使用了
UINavigationController
,并且
TestController
viewDidLoad
中的
self.view.translatesAutoResizezingMaskintoConstraints=false
被注释掉):

但这似乎不是一个合适的解决方案。我需要一个
UINavigationController
来创建我的应用程序结构。问题是,当我不使用上述任何解决方案时,我会得到一个黑屏,中间有一个按钮(在两个轴上)。这些观点似乎被打破了:

想法?我是否应该删除self.view.translatesAutoresizingMaskIntoConstraints=false并忘记它,还是确实需要它?如果是,我的代码一定有问题

更新2:

有趣的教程:。作者不在
viewDidLoad
中使用
self.view.translatesAutoResizengMaskintoConstraints=false
,仅在子视图上使用

更新3:

我想我可能已经通过将
self.view.translatesAutoresizingMaskIntoConstraints=false
移动到
init
方法而不是
viewDidLoad
解决了黑屏问题。虽然不知道为什么会这样,但屏幕看起来与现在的截图完全相同,正如我最初打算的那样。以下是更新的代码:

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 < 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' => self.view, 
      'button' => @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
类AppDelegate
def应用程序(应用程序,DidFinishLaunchWithOptions:launchOptions)
@window=UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds)。点击do | win|
controller=TestController.alloc.initWithNibName(nil,bundle:nil)
win.rootViewController=UINavigationController.alloc.initWithRootViewController(controller)。点击do | root|
root.navigationBarHidden=true
root.wantsFullScreenLayout=true
结束
win.makeyAndVisible
结束
真的
结束
结束
类TestControllerself.view,
“按钮”=>@按钮
}
self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat('H:[按钮(100)],选项:0,度量:nil,视图:视图))
self.view.addConstraint(NSLayoutConstraint.constraintWithItem(@按钮,属性:NSLayoutAttributeCenter,关联者:NSLayoutRelationEqual,toItem:self.view,属性:NSLayoutAttributeCenter,乘数:1,常数:0))
self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat('V:[按钮]-|',选项:0,度量:nil,视图:视图))
结束
结束

我希望这个答案有帮助。我知道有点晚了,但我刚刚遇到了你的问题。你的代码正常,但我遇到了另一个问题。在app委托中,我在窗口对象上使用
rootViewController
,并使用
UINavigationController
初始化包含上述代码的另一个控制器。如果我运行代码,背景是黑色的,底部是中间的(在两个轴上)。但是,当我删除“self.translatesAutoresizingMaskIntoConstraints=NO;”在相应的
UIViewController
viewdiload
行中,代码工作。但是这一行不是应该存在吗?另一个解决方案似乎是将窗口对象的
rootViewController
直接设置到相应的
UIViewController
,而不是使用
UINavigationController
,并保留该行
self.translatesAutoResizengAskintoConstraints=NO
viewdiload
中完好无损。现在代码也可以工作了。但这似乎并不正确,因为构建应用程序结构需要
UINavigationController
。WWDC 2012年会议视频(11:40开始)建议
setTranslatesAutoResizengMarkintoConstraints:NO
以编程方式创建视图。很抱歉,我对视图控制器了解不够,无法帮助您回答其余问题。也许发布屏幕截图会吸引新的答案。这也是我从2012年WWDC会议视频中了解到的。他们提到这一行应该始终存在,否则自动布局可能会表现不稳定。奇怪的是,这一行正是导致我的代码出现问题的原因。我添加了截图。无论如何,因为你已经回答了我最初的问题,我会接受你的回答。希望其他人能用黑屏来澄清我的问题。谢谢你的帮助!我希望这个答案有帮助。我知道有点晚了,但我刚刚遇到了你的问题。你的代码正常,但我遇到了另一个问题。在app委托中,我在窗口对象上使用
rootViewController
,并使用
UINavigationController
初始化包含上述代码的另一个控制器。如果我运行代码,t
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 < 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' => self.view, 
      'button' => @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
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 < 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' => self.view, 
      'button' => @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
UIButton* button = [UIButton buttonWithType:UIButtonTypeRoundedRect] ;
button.translatesAutoresizingMaskIntoConstraints = NO ;
[self.view addSubview:button] ;

NSDictionary* views = @{ @"view" : self.view  ,  @"button" : button } ;
// Make button's width 100.
[self.view addConstraints: [NSLayoutConstraint constraintsWithVisualFormat:@"H:[button(100)]"  options:0   metrics:nil  views:views ] ] ;
// Make button's CenterX the same as self.view's CenterX.
[self.view addConstraint: [NSLayoutConstraint constraintWithItem:button  attribute:NSLayoutAttributeCenterX  relatedBy:NSLayoutRelationEqual  toItem:self.view  attribute:NSLayoutAttributeCenterX  multiplier:1  constant:0 ] ] ;
// Make button's NSLayoutAttributeBottom the default space away from self.view's NSLayoutAttributeBottom.
[self.view addConstraints: [NSLayoutConstraint constraintsWithVisualFormat:@"V:[button]-|"  options:0   metrics:nil  views:views ] ] ;