I created a “tooltip” that has a UILabel and a UIView with a CAShapeLayer for the shape of a triangle. I set the “tip” so that the label is on top and the triangle is attached to the bottom and centered on UILabel.
When I show the “hint”, I use UIViewAnimation with Spring Damping and Spring Velocity to give it a “pop animation”. This works great, with one exception, you can notice a small gap between the triangle and the UILabel at the beginning of the animation (which is then fixed when the animation ends.
Any suggestions on how to fix this?
Here is the view / restriction setting:
let containerView = UIView()
containerView.alpha = 1.0
containerView.layer.cornerRadius = 5.0
containerView.clipsToBounds = true
containerView.backgroundColor = UIColor.orangeColor()
self.addSubview(containerView)
self.containerView = containerView
let titleLabel = UILabel()
titleLabel.font = UIFont.systemFontOfSize(14.0)
titleLabel.textColor = UIColor.whiteColor()
titleLabel.numberOfLines = 0
titleLabel.adjustsFontSizeToFitWidth = true
containerView.addSubview(titleLabel)
self.titleLabel = titleLabel
let triangleView = UIView()
self.addSubview(triangleView)
self.triangleView = triangleView
let views: [String: UIView] = [
"containerView" : containerView,
"titleLabel" : titleLabel,
"triangleView" : triangleView,
]
let metrics = [String:AnyObject]()
for (_, view) in views {
view.translatesAutoresizingMaskIntoConstraints = false
}
NSLayoutConstraint.activateConstraints(NSLayoutConstraint.constraintsWithVisualFormat("|-8-[titleLabel]-8-|", options: [], metrics: metrics, views: views))
NSLayoutConstraint.activateConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-8-[titleLabel]-8-|", options: [], metrics: metrics, views: views))
let widthConstraint = NSLayoutConstraint(item: self, attribute: .Width, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant: 0)
widthConstraint.active = true
self.widthConstraint = widthConstraint
let heightConstraint = NSLayoutConstraint(item: self, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant: 0)
heightConstraint.active = true
self.heightConstraint = heightConstraint
let trianglePath = UIBezierPath()
trianglePath.moveToPoint(CGPoint(x: 0, y: 0))
trianglePath.addLineToPoint(CGPoint(x: 8.0, y: 10.0))
trianglePath.addLineToPoint(CGPoint(x: 16.0, y: 0))
trianglePath.closePath()
let mask = CAShapeLayer()
mask.frame = triangleView.bounds
mask.path = trianglePath.CGPath
triangleView.layer.mask = mask
NSLayoutConstraint.activateConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[containerView][triangleView]|", options: [], metrics: metrics, views: views))
NSLayoutConstraint.activateConstraints(NSLayoutConstraint.constraintsWithVisualFormat("|[containerView]|", options: [], metrics: metrics, views: views))
NSLayoutConstraint.activateConstraints(NSLayoutConstraint.constraintsWithVisualFormat("|-(>=8)-[self]-(>=8)-|", options: [], metrics: metrics, views: views))
NSLayoutConstraint.activateConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-(>=8)-[self][anchorView]", options: [], metrics: metrics, views: views))
NSLayoutConstraint.activateConstraints(NSLayoutConstraint.constraintsWithVisualFormat("[triangleView(>=16)]", options: [], metrics: metrics, views: views))
NSLayoutConstraint.activateConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:[triangleView(>=10)]", options: [], metrics: metrics, views: views))
NSLayoutConstraint(item: self.triangleView, attribute: .CenterX, relatedBy: .Equal, toItem: self.anchorView, attribute: .CenterX, multiplier: 1.0, constant: 1.0).active = true
let centerXConstraint = NSLayoutConstraint(item: triangleView, attribute: .CenterX, relatedBy: .Equal, toItem: containerView, attribute: .CenterX, multiplier: 1.0, constant: 0.0)
centerXConstraint.priority = UILayoutPriorityDefaultLow
centerXConstraint.active = true
Here is the animation script:
self.layoutIfNeeded()
self.widthConstraint.active = false
self.heightConstraint.active = false
UIView.animateWithDuration(0.5, delay: 0, usingSpringWithDamping: 0.7, initialSpringVelocity: 0.5, options: .CurveEaseInOut, animations: { () -> Void in
self.alpha = 1.0
self.layoutIfNeeded()
}, completion: nil)
Video:
