Percentage based percentage using autorun

I am trying to put my subview with a left margin based on the width of the parent view. It sounds simple, but I can't figure out how to do this using autorun.

Logically, I would need to set the left margin value with a certain percentage value of the parent width, but at the moment I can not translate this logic into auto-detection.

This is my code at the moment:

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

Here the code returns an error:

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

Error:

* Application termination due to the uncaught exception 'NSInvalidArgumentException', reason: '* + [NSLayoutConstraint constraintWithItem: attribute: relatedBy: toItem: attribute: multiplier: constant]: Invalid mate attributes pairing

Does anyone have any ideas on how to achieve this? I just want the left margin to be 0.75% of the width of the parent's view.

Thanks.

+6
source share
4 answers

You want the left sview be at some point on the left of the view , and you write that you want the left side of the sview at some point in the width of the view , which does not correspond to the correct conjugation of the layout attributes, as your error says.

Here is what you need to do:

 NSLayoutConstraint(item: sview, attribute: NSLayoutAttribute.Left, relatedBy: NSLayoutRelation.Equal, toItem: view, attribute: NSLayoutAttribute.Left, multiplier: 1, constant: (CGRectGetWidth(view.bounds) * 0.75)); 

Hope this helps!

EDIT

I found an excellent article on interest margins:
http://simblestudios.com/blog/development/percentage-width-in-autolayout.html
Or even simpler:
http://simblestudios.com/blog/development/easier-percentage-width-in-autolayout.html

enter image description here

+7
source

You can create percentage fields with automatic layout restrictions between the subview and its superview. Margin will dynamically change as the size of the add-in changes. For example, here's how to create a final 10% margin.

  • Create a trailing constraint between your view and its add-in.
  • Verify that the first element of the constraint is a preview, and the second element is a superstructure. This can be done by clicking on the first item and selecting “Reverse First” and “Second Element”.
  • Change the constant value of the constraint to zero in the attribute inspector.
  • Change the multiplier to 0.9.

enter image description here

This is one of the problems with this manual approach, although, for example, it does not work in the language from right to left, for example, in Arabic. From right to left, layouts require slightly different settings to limit, but we cannot keep both in the same storyboard.

Here is a library that I wrote that allows you to create percent based restrictions. It processes the right-handed language.

https://github.com/exchangegroup/PercentageMargin

+5
source

You can subclass NSLayoutConstraint to accept the margin percentage through @IBInspectable . Then subscribe to UIDeviceOrientationDidChangeNotification to run the calculation and material to constant so that it is updated whenever the layout changes.

 /// 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) } } 

First, you specify a new subclass in the Identity Inspector : enter image description here

Then you can use it as follows: enter image description here

The only caveat I can think of is constants in the storyboard, which are not used at run time, but are instead overwritten by percent based calculations. Thus, this requires some duplication of effort as soon as you actually arrange the views on the Storyboard based on glasses so that you understand what the screen layout looks like and then the percentages are clicked at runtime.

See this article for more details: http://basememara.com/percentage-based-margin-using-autolayout-storyboard/

+1
source

Along with Kevin's answer, you also need to add a constraint for the supervisor.

 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)); 
0
source

Source: https://habr.com/ru/post/978824/


All Articles