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:
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
Post a Comment