Image for reference:
I need to animate from the leftmost shape to the rightmost shape. I have included intermediate frames as an example of what is so tricky about this (and necessary for the design): the corner radius effect where the two rectangles meet.
class TestRoundedCornerViews: UIView {
let leftView = UIView()
let middleView = UIView()
let rightView = UIView()
override init(frame: CGRect) {
super.init(frame: frame)
let cornerRadius: CGFloat = 16
leftView.layer.cornerRadius = cornerRadius
leftView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMinXMaxYCorner]
self.addSubview(self.leftView)
middleView.layer.cornerRadius = cornerRadius
middleView.layer.maskedCorners = [.layerMaxXMinYCorner, .layerMaxXMaxYCorner]
self.addSubview(self.middleView)
rightView.layer.cornerRadius = cornerRadius
rightView.layer.maskedCorners = [.layerMaxXMinYCorner, .layerMaxXMaxYCorner]
self.addSubview(self.rightView)
}
// MARK: Layout
override func layoutSubviews() {
super.layoutSubviews()
let leftSideWidth: CGFloat = 100
let leftViewWidth: CGFloat = leftSideWidth / 2
let middleViewWidth: CGFloat = leftViewWidth
let rightViewWidth: CGFloat = 40
leftView.frame = CGRect(
x: 0,
y: 0,
width: leftViewWidth,
height: self.bounds.height
)
middleView.frame = CGRect(
x: leftView.frame.maxX,
y: 0,
width: middleViewWidth,
height: self.bounds.height
)
rightView.frame = CGRect(
x: middleView.frame.maxX,
y: 0,
width: rightViewWidth,
height: self.bounds.height
)
}
required init?(coder: NSCoder) {
fatalError()
}
}
Here's a visual of what that ends up like, using 3 views:
However it does not have that corner radius where the views meet, and I do not know how to animate that to the end position.


I did this animation by animating a
CAShapeLayerpath.We start by adding 8 arcs to a
UIBezierPath"startPath" (the connecting lines are automatically added):Then we create an "endPath" moving the centers ... and we decreasing the radius to Zero where needed (arcs 2, 3, 6, 7):
We can then use
CABasicAnimation(keyPath: "path")with.fromValue = startPath.cgPathand.toValue = endPath.cgPathto "morph" from one shape to another.You'll notice near the end of the animation that the corners being "straightened out" get a little "stepping" effect as their radius nears Zero... with some more math, and possibly chaining a few animations together, we could probably make that a little cleaner.
However, how noticeable it is depends on the speed of the animation and the overall size of the view, and may not be worth the effort.
Here's an example view subclass to do this:
and here's a simple view controller that shows the view (at
150 x 300size), then animates on tap: