我创建了一个"工具提示"具有UILabel的视图和带有CAShapeLayer的UIView用于三角形形状。 我已经设置了"工具提示"这样标签就在上面,三角形贴在底部,并以UILabel为中心。
当我显示"工具提示"时,我使用带弹簧阻尼和弹簧速度的UIViewAnimation给它一个" pop"动画。这很有效,只有一个例外,在动画开始时三角形和UILabel之间可以注意到一个小间隙(然后在动画结束时修复。
有关如何解决此问题的任何建议吗?
以下是视图/约束设置:
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 // Required to allow tooltip to grow beyond anchorView bounds without changing the anchorView constraints.
centerXConstraint.active = true
以下是动画脚本:
self.layoutIfNeeded() // Set starting position for tooltip before animation
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)
答案 0 :(得分:1)
接近它的一种方法是拥有自定义UILabel
class ToolTip: UILabel {
var roundRect:CGRect!
override func drawTextInRect(rect: CGRect) {
super.drawTextInRect(roundRect)
}
override func drawRect(rect: CGRect) {
roundRect = CGRect(x: rect.minX, y: rect.minY, width: rect.width, height: rect.height * 4 / 5)
let roundRectBez = UIBezierPath(roundedRect: roundRect, cornerRadius: 10.0)
let triangleBez = UIBezierPath()
triangleBez.moveToPoint(CGPoint(x: roundRect.minX + roundRect.width / 2.5, y:roundRect.maxY))
triangleBez.addLineToPoint(CGPoint(x:rect.midX,y:rect.maxY))
triangleBez.addLineToPoint(CGPoint(x: roundRect.maxX - roundRect.width / 2.5, y:roundRect.maxY))
triangleBez.closePath()
roundRectBez.appendPath(triangleBez)
let bez = roundRectBez
UIColor.lightGrayColor().setFill()
bez.fill()
super.drawRect(rect)
}
}
然后像这样执行布局和动画:
import UIKit
class ViewController: UIViewController {
var label:ToolTip!
var labelTransform:CGAffineTransform!
let buttonHeight:CGFloat = 100
let buttonWidth:CGFloat = 200
override func viewDidLoad() {
super.viewDidLoad()
let button = UIButton()
button.setTitle("Push Me", forState: .Normal)
button.addTarget(self, action: Selector("buttonPushed"), forControlEvents: .TouchUpInside)
button.backgroundColor = UIColor.orangeColor()
view.addSubview(button)
button.translatesAutoresizingMaskIntoConstraints = false
button.centerXAnchor.constraintEqualToAnchor(view.centerXAnchor).active = true
button.centerYAnchor.constraintEqualToAnchor(view.centerYAnchor).active = true
button.heightAnchor.constraintEqualToConstant(buttonHeight).active = true
button.widthAnchor.constraintEqualToConstant(buttonWidth).active = true
label = ToolTip()
view.insertSubview(label, belowSubview: button)
label.translatesAutoresizingMaskIntoConstraints = false
label.heightAnchor.constraintEqualToConstant(buttonHeight).active = true
label.widthAnchor.constraintEqualToConstant(buttonWidth).active = true
label.bottomAnchor.constraintEqualToAnchor(button.topAnchor).active = true
label.centerXAnchor.constraintEqualToAnchor(view.centerXAnchor).active = true
label.text = "This button is orange!"
label.textColor = UIColor.whiteColor()
label.textAlignment = .Center
let trans1 = CGAffineTransformMakeScale(0, 0)
let trans2 = CGAffineTransformMakeTranslation(0, buttonHeight)
labelTransform = CGAffineTransformConcat(trans1, trans2)
label.transform = labelTransform
}
func buttonPushed() {
if label.transform.ty > 0 {
UIView.animateWithDuration(0.75, delay: 0, usingSpringWithDamping: 0.7, initialSpringVelocity: 0.5, options: .CurveEaseInOut, animations: { () -> Void in
self.label.transform = CGAffineTransformIdentity
}, completion: nil)
}
else {
UIView.animateWithDuration(0.5, delay: 0, options: .CurveEaseInOut, animations: { () -> Void in
self.label.alpha = 0
}, completion: {_ in
self.label.transform = self.labelTransform
self.label.alpha = 1
}) }
}
}
创建以下效果: