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