0

请看以下代码:

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),这个按钮就会延伸到屏幕宽度减去默认边距。当我指定自定义宽度时,我认为自动布局系统无法计算出左右边距应该是什么。我得到一个Unable to simultaneously satisfy constraints.错误。我想这与 中的破折号有关H:|-[start(100)]-|,它需要具有流体宽度才能将start元素附加到superview,而不是默认边距。

关于我如何解决这个问题的任何想法?

更新(感谢 ghettopia):

这有效(注意我UINavigationController在应用程序委托中使用 a 并且inself.view.translatesAutoresizingMaskIntoConstraints = false被注释掉了):viewDidLoadTestController

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 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

正确的画面

伟大的。现在我得到一个蓝屏,按钮以 X 轴为中心,底部有默认边距,正如我想要的那样。但是,根据我所阅读self.view.translatesAutoresizingMaskIntoConstraints = false的内容,需要使自动布局工作。为了实现这一点,这也有效(请注意,我UINavigationController这次没有使用 a 并且self.view.translatesAutoresizingMaskIntoConstraints = false正在viewDidLoad使用TestControllerIS):

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

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

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

更新 2:

有趣的教程:iOS 6 中的自动布局:通过代码添加约束。作者不使用self.view.translatesAutoresizingMaskIntoConstraints = falsein viewDidLoad,仅在子视图上使用。

更新 3:

我想我可能已经通过转移self.view.translatesAutoresizingMaskIntoConstraints = falseinit方法而不是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
4

1 回答 1

6
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 ] ] ;
于 2012-12-15T18:56:06.680 回答