Skip to content

Commit 99ab4ee

Browse files
authored
Merge pull request #116 from mirego/handle_relative_position_with_anchorpoint_and_transforms
Handle relative layout with a view with a transforms and/or a modified anchorPoint
2 parents 89986ba + e2db7a6 commit 99ab4ee

File tree

2 files changed

+66
-3
lines changed

2 files changed

+66
-3
lines changed

Sources/Impl/Coordinates.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,10 +109,12 @@ class Coordinates {
109109
By setting the view's center and bounds we really set the frame of the non-transformed view, and this keep
110110
the view's transform. So view's transforms won't be affected/altered by PinLayout.
111111
*/
112-
let bounds = view.bounds
113-
let origin = CGPoint(x: view.center.x - bounds.width / 2, y: view.center.y - bounds.height / 2)
112+
let size = view.bounds.size
113+
// See setUntransformedViewRect(...) for details about this calculation.
114+
let origin = CGPoint(x: view.center.x - (size.width * view.layer.anchorPoint.x),
115+
y: view.center.y - (size.height * view.layer.anchorPoint.y))
114116

115-
return CGRect(origin: origin, size: bounds.size)
117+
return CGRect(origin: origin, size: size)
116118
}
117119

118120
static func roundFloatToDisplayScale(_ pointValue: CGFloat) -> CGFloat {

Tests/TransformSpec.swift

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,68 @@ class TransformSpec: QuickSpec {
493493
expect(aView.bounds).to(equal(CGRect(x: 0, y: 0, width: 100.0, height: 100.0)))
494494
expect(aView.center).to(equal(CGPoint(x: 100, y: 100)))
495495
}
496+
}
497+
498+
describe("when a view is layouted relative to a view with a modified anchorPoint and/or scale transform") {
499+
it("should layout the bView correctly below the relative view with an anchorPoint of (0.5, 0.5)") {
500+
aView.pin.top(100).left(100).width(100).height(100)
501+
bView.pin.below(of: aView, aligned: .left)
502+
503+
expect(aView.frame).to(equal(CGRect(x: 100.0, y: 100.0, width: 100.0, height: 100.0)))
504+
505+
expect(bView.frame).to(equal(CGRect(x: 100.0, y: 200.0, width: 100.0, height: 50.0)))
506+
expect(bView.bounds).to(equal(CGRect(x: 0, y: 0, width: 100.0, height: 50.0)))
507+
expect(bView.center).to(equal(CGPoint(x: 150, y: 225)))
508+
}
509+
510+
it("should layout the bView correctly below the relative view with an anchorPoint of (0.25, 0.25)") {
511+
aView.layer.anchorPoint = CGPoint(x: 0.25, y: 0.25) // default is 0.5, 0.5 (Center)
512+
aView.pin.top(100).left(100).width(100).height(100)
513+
514+
bView.pin.below(of: aView, aligned: .left)
515+
516+
expect(aView.frame).to(equal(CGRect(x: 100.0, y: 100.0, width: 100.0, height: 100.0)))
517+
expect(aView.bounds).to(equal(CGRect(x: 0, y: 0, width: 100.0, height: 100.0)))
518+
expect(aView.center).to(equal(CGPoint(x: 125, y: 125)))
519+
520+
expect(bView.frame).to(equal(CGRect(x: 100.0, y: 200.0, width: 100.0, height: 50.0)))
521+
expect(bView.bounds).to(equal(CGRect(x: 0, y: 0, width: 100.0, height: 50.0)))
522+
expect(bView.center).to(equal(CGPoint(x: 150, y: 225)))
523+
}
496524

525+
it("should layout the bView correctly below the relative view with an anchorPoint of (0, 1) and a scale x2") {
526+
aView.layer.anchorPoint = CGPoint(x: 0, y: 1) // default is 0.5, 0.5 (Center)
527+
aView.transform = CGAffineTransform(scaleX: 2, y: 2)
528+
aView.pin.top(100).left(100).width(100).height(100)
529+
530+
bView.pin.below(of: aView, aligned: .left)
531+
532+
expect(aView.frame).to(equal(CGRect(x: 100.0, y: 0.0, width: 200.0, height: 200.0)))
533+
expect(aView.bounds).to(equal(CGRect(x: 0, y: 0, width: 100.0, height: 100.0)))
534+
expect(aView.center).to(equal(CGPoint(x: 100, y: 200)))
535+
536+
expect(bView.frame).to(equal(CGRect(x: 100.0, y: 200.0, width: 100.0, height: 50.0)))
537+
expect(bView.bounds).to(equal(CGRect(x: 0, y: 0, width: 100.0, height: 50.0)))
538+
expect(bView.center).to(equal(CGPoint(x: 150, y: 225)))
539+
}
540+
541+
it("should layout the bView correctly with aView and bView modified anchorPoint + scale") {
542+
aView.layer.anchorPoint = CGPoint(x: 0, y: 1) // default is 0.5, 0.5 (Center)
543+
aView.transform = CGAffineTransform(scaleX: 2, y: 2)
544+
aView.pin.top(100).left(100).width(100).height(100)
545+
546+
bView.layer.anchorPoint = CGPoint(x: 0, y: 0) // default is 0.5, 0.5 (Center)
547+
bView.transform = CGAffineTransform(scaleX: 4, y: 2)
548+
bView.pin.below(of: aView, aligned: .left)
549+
550+
expect(aView.frame).to(equal(CGRect(x: 100.0, y: 0.0, width: 200.0, height: 200.0)))
551+
expect(aView.bounds).to(equal(CGRect(x: 0, y: 0, width: 100.0, height: 100.0)))
552+
expect(aView.center).to(equal(CGPoint(x: 100, y: 200)))
553+
554+
expect(bView.frame).to(equal(CGRect(x: 100.0, y: 200.0, width: 400.0, height: 100.0)))
555+
expect(bView.bounds).to(equal(CGRect(x: 0, y: 0, width: 100.0, height: 50.0)))
556+
expect(bView.center).to(equal(CGPoint(x: 100, y: 200)))
557+
}
497558
}
498559
}
499560
}

0 commit comments

Comments
 (0)