objective c - Defining NSLayoutConstraints to include rectangles inside a view -


i have input data in format of:

[   {{0,0}, {0.3, 0.8}},   {{0.4, 0.2}, {0.3, 0.2}} ] 

so they're string representation of cgrects contained in 1x1 rectangle.

now need display them on screen, inside uiview thats dimensions calculated using auto layout. wanted translate nslayoutconstraints, inside rectangles resize superview resizes.

i can set width , height of subviews pretty easily. in loop on rects array create new uiview:

cgrect r = cgrectfromstring(rectstring) uiview *rect = [[uiview alloc] init]; [superview addsubview:rect]; nslayoutconstraint *width = [nslayoutconstraint            constraintwithitem: rect           attribute: nslayoutattributewidth           relatedby: nslayoutrelationequal           toitem: superview           attribute: nslayoutattributewidth           multiplier: r.size.width           constant:0]; [superview addconstraint:width]; 

the same goes height.

but when want set x , y coordinates of rectangles based on width , height of superview, error.

my code:

nslayoutconstraint * left = [nslayoutconstraint                                               constraintwithitem: rect                                                       attribute: nslayoutattributeleft                                                       relatedby: nslayoutrelationequal                                                          toitem: superview                                                       attribute: nslayoutattributewidth                                                      multiplier: r.origin.x                                                        constant: 0]; [superview addconstraint: left]; 

if r.origin.x 0, error is: a multiplier of 0 or nil second item location first attribute creates illegal constraint of location equal constant. location attributes must specified in pairs.

in other cases (when it's not 0), error reads: invalid pairing of layout attributes. seems can't mix nslayoutattributeleft , nslayoutattributewidth.

is there way lay out subviews that, without creating complex subviews structure inside (like, adding special "spacing" view between left/top edges of superview , top-left corner of rectangle)?

instead of constraining left width multiplier , right height multiplier, suggest constraining right right multiplier of origin.x + size.width , bottom bottom multiplier of origin.y + size.height.

here implementation in swift demonstrates rectangle values. using swift allows me show results in playground.

let superview = uiview(frame: cgrect(x: 0, y: 0, width: 200, height: 200)) superview.backgroundcolor = .yellowcolor()  let rectstrings = ["{{0,0}, {0.3, 0.8}}", "{{0.4, 0.2}, {0.3, 0.2}}"] let colors: [uicolor] = [.bluecolor(), .redcolor()]  in 0 ..< rectstrings.count {     let r = cgrectfromstring(rectstrings[i])      let rect = uiview()     rect.translatesautoresizingmaskintoconstraints = false     rect.backgroundcolor = colors[i]     superview.addsubview(rect)      nslayoutconstraint(item: rect, attribute: .width, relatedby: .equal, toitem: superview,         attribute: .width, multiplier: r.size.width, constant: 0).active = true      nslayoutconstraint(item: rect, attribute: .height, relatedby: .equal, toitem: superview,         attribute: .height, multiplier: r.size.height, constant: 0).active = true      nslayoutconstraint(item: rect, attribute: .right, relatedby: .equal, toitem: superview,         attribute: .right, multiplier: r.origin.x + r.size.width, constant: 0).active = true      nslayoutconstraint(item: rect, attribute: .bottom, relatedby: .equal, toitem: superview,         attribute: .bottom, multiplier: r.origin.y + r.size.height, constant: 0).active = true }  superview.layoutifneeded() 

here running in swift playground:

playground demonstration of rectangle constraints


here's equivalent in objective-c. superview iboutlet view laid out in storyboard:

nsarray *rectstrings = @[@"{{0,0}, {0.3, 0.8}}", @"{{0.4, 0.2}, {0.3, 0.2}}"]; nsarray *colors = @[[uicolor bluecolor], [uicolor redcolor]];  (int = 0; < rectstrings.count; i++) {     cgrect r = cgrectfromstring(rectstrings[i]);      uiview *rect = [[uiview alloc] init];      rect.translatesautoresizingmaskintoconstraints = false;      rect.backgroundcolor = colors[i];     [self.superview addsubview: rect];      [nslayoutconstraint constraintwithitem: rect                                  attribute: nslayoutattributewidth                                  relatedby: nslayoutrelationequal                                     toitem: self.superview                                  attribute: nslayoutattributewidth                                 multiplier: r.size.width                                   constant: 0].active = yes;      [nslayoutconstraint constraintwithitem: rect                                  attribute: nslayoutattributeheight                                  relatedby: nslayoutrelationequal                                     toitem: self.superview                                  attribute: nslayoutattributeheight                                 multiplier: r.size.height                                   constant: 0].active = yes;      [nslayoutconstraint constraintwithitem: rect                                  attribute: nslayoutattributeright                                  relatedby: nslayoutrelationequal                                     toitem: self.superview                                  attribute: nslayoutattributeright                                 multiplier: r.origin.x + r.size.width                                   constant: 0].active = yes;      [nslayoutconstraint constraintwithitem: rect                                  attribute: nslayoutattributebottom                                  relatedby: nslayoutrelationequal                                     toitem: self.superview                                  attribute: nslayoutattributebottom                                 multiplier: r.origin.y + r.size.height                                   constant: 0].active = yes; }  [self.superview layoutifneeded]; 

this answer based upon rectangle values in 1x1 rectangle stated in question. make work sized rectangle, divide width , height of rectangle.

for instance, if rectangles were:

let rectstrings = ["{{0,0}, {3.0, 8.0}}", "{{4.0, 2.0}, {3.0, 2.0}}"] 

and size of rectangle 10 wide 20 high, you'd scale values dividing width , height.

the width, height, right, , bottom multipliers be:

r.size.width / 10.0 r.size.height / 20.0 (r.origin.x + r.size.width) / 10.0 (r.origin.y + r.size.height) / 20.0 

Comments

Popular posts from this blog

php - Wordpress website dashboard page or post editor content is not showing but front end data is showing properly -

How to get the ip address of VM and use it to configure SSH connection dynamically in Ansible -

javascript - Get parameter of GET request -