我正在尝试使用基于父视图宽度的左边距放置我的子视图。这听起来很简单,但我无法弄清楚如何使用autolayout来做到这一点。
逻辑上,我只需要将左边距值设置为父宽度的某个百分比值,但此刻,我无法将该逻辑转换为自动布局。
这是我目前的代码:
var view = UIView();
view.backgroundColor = UIColor.redColor();
view.frame = CGRectMake(0, 0, 320, 400);
var sview = UIView();
sview.setTranslatesAutoresizingMaskIntoConstraints(false);
sview.backgroundColor = UIColor.yellowColor();
//sview.frame = CGRectMake(0, 0, 50, 50);
view.addSubview(sview);
var dict = Dictionary<String, UIView>()
dict["box"] = sview;
var con1 = NSLayoutConstraint(item: sview, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: view, attribute: NSLayoutAttribute.Top, multiplier: 1.0, constant: 20.0);
view.addConstraint(con1);
var con2 = NSLayoutConstraint(item: sview, attribute: NSLayoutAttribute.Left, relatedBy: NSLayoutRelation.Equal, toItem: view, attribute: NSLayoutAttribute.Width, multiplier: 0.75, constant: 0.0);
view.addConstraint(con2);
var con3 = NSLayoutConstraint(item: sview, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: view, attribute: NSLayoutAttribute.Width, multiplier: 1.0, constant: 0.0);
view.addConstraint(con3);
var con4 = NSLayoutConstraint(item: sview, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: view, attribute: NSLayoutAttribute.Height, multiplier: 1.0, constant: 0.0);
view.addConstraint(con4);
这是代码返回错误的地方:
var con2 = NSLayoutConstraint(item: sview, attribute: NSLayoutAttribute.Left, relatedBy: NSLayoutRelation.Equal, toItem: view, attribute: NSLayoutAttribute.Width, multiplier: 0.75, constant: 0.0);
view.addConstraint(con2);
错误:
*由于未捕获的异常'NSInvalidArgumentException'而终止应用,原因:'* + [NSLayoutConstraint constraintWithItem:属性:relatedBy:toItem:属性:乘数:常数:]: 布局属性的配对无效
有没有人知道如何实现这个目标?我只想让左边距为父视图宽度的0.75%。
感谢。
答案 0 :(得分:8)
你想要的是sview
的左位于view
的 左的某个点并且您写道,您希望sview
的左侧位于view
宽度的某个点,这不是您的错误所说的布局属性的正确配对。
以下是您需要做的事情:
NSLayoutConstraint(item: sview,
attribute: NSLayoutAttribute.Left,
relatedBy: NSLayoutRelation.Equal,
toItem: view,
attribute: NSLayoutAttribute.Left,
multiplier: 1,
constant: (CGRectGetWidth(view.bounds) * 0.75));
希望它有所帮助!
修改强>
我发现了一篇关于基于Percented的边距的精彩文章:
http://simblestudios.com/blog/development/percentage-width-in-autolayout.html
甚至更简单:
http://simblestudios.com/blog/development/easier-percentage-width-in-autolayout.html
答案 1 :(得分:5)
可以在子视图及其超级视图之间创建具有自动布局约束的基于百分比的边距。随着超视图的大小变化,边距将动态变化。例如,这是如何创建10%的追踪保证金。
这是手动方法的一个问题 - 例如,它不适用于从右到左的语言,阿拉伯语。从右到左的布局需要对约束进行一些不同的设置,但我们不能将它们保留在一个故事板中。
这是我编写的一个库,可以让您创建基于百分比的约束。它确实处理了从右到左的语言案例。
答案 2 :(得分:1)
您可以通过NSLayoutConstraint
将@IBInspectable
子类化为接受保证金百分比。然后订阅UIDeviceOrientationDidChangeNotification
以运行计算并填入constant
值,以便在布局更改时更新。
/// Layout constraint to calculate size based on multiplier.
class PercentLayoutConstraint: NSLayoutConstraint {
@IBInspectable var marginPercent: CGFloat = 0
var screenSize: (width: CGFloat, height: CGFloat) {
return (UIScreen.mainScreen().bounds.width, UIScreen.mainScreen().bounds.height)
}
override func awakeFromNib() {
super.awakeFromNib()
guard marginPercent > 0 else { return }
NSNotificationCenter.defaultCenter().addObserver(self,
selector: #selector(layoutDidChange),
name: UIDeviceOrientationDidChangeNotification,
object: nil)
}
/**
Re-calculate constant based on orientation and percentage.
*/
func layoutDidChange() {
guard marginPercent > 0 else { return }
switch firstAttribute {
case .Top, .TopMargin, .Bottom, .BottomMargin:
constant = screenSize.height * marginPercent
case .Leading, .LeadingMargin, .Trailing, .TrailingMargin:
constant = screenSize.width * marginPercent
default: break
}
}
deinit {
guard marginPercent > 0 else { return }
NSNotificationCenter.defaultCenter().removeObserver(self)
}
}
我能想到的唯一警告是故事板中的常量不会在运行时使用,而是会被基于百分比的计算覆盖。所以它确实需要一些重复的工作,一次是基于点在Storyboard上实际布局视图,这样你就可以了解屏幕布局的样子,然后在运行时启动百分比。
有关详细信息,请查看此文章:http://basememara.com/percentage-based-margin-using-autolayout-storyboard/
答案 3 :(得分:0)
除了凯文回答,您还需要为方框超级视图添加约束。
var view = UIView();
view.backgroundColor = UIColor.redColor();
view.setTranslatesAutoresizingMaskIntoConstraints(false);
self.view.addSubview(view);
var viewObject = ["mainview" : self.view , "view" : view];
self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:[view(==320)]", options: NSLayoutFormatOptions(0), metrics: nil, views: viewObject));
self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:[view(==400)]", options: NSLayoutFormatOptions(0), metrics: nil, views: viewObject));