答案 0 :(得分:2)
您可以通过向CALayer
添加按钮内容的较浅版本,然后遮盖该层并设置遮罩动画来创建类似效果。例如:
extension UIButton {
func flash() {
// Take as snapshot of the button and render as a template
let snapshot = self.snapshot?.withRenderingMode(.alwaysTemplate)
let imageView = UIImageView(image: snapshot)
// Add it image view and render close to white
imageView.tintColor = UIColor(white: 0.9, alpha: 1.0)
guard let image = imageView.snapshot else { return }
let width = image.size.width
let height = image.size.height
// Create CALayer and add light content to it
let shineLayer = CALayer()
shineLayer.contents = image.cgImage
shineLayer.frame = bounds
// create CAGradientLayer that will act as mask clear = not shown, opaque = rendered
// Adjust gradient to increase width and angle of highlight
let gradientLayer = CAGradientLayer()
gradientLayer.colors = [UIColor.clear.cgColor,
UIColor.clear.cgColor,
UIColor.black.cgColor,
UIColor.clear.cgColor,
UIColor.clear.cgColor]
gradientLayer.locations = [0.0, 0.35, 0.50, 0.65, 0.0]
gradientLayer.startPoint = CGPoint(x: 0.0, y: 0.0)
gradientLayer.endPoint = CGPoint(x: 1.0, y: 0.0)
gradientLayer.frame = CGRect(x: -width, y: 0, width: width, height: height)
// Create CA animation that will move mask from outside bounds left to outside bounds right
let animation = CABasicAnimation(keyPath: "position.x")
animation.byValue = width * 2
// How long it takes for glare to move across button
animation.duration = 3
// Repeat forever
animation.repeatCount = Float.greatestFiniteMagnitude
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
layer.addSublayer(shineLayer)
shineLayer.mask = gradientLayer
// Add animation
gradientLayer.add(animation, forKey: "shine")
}
func stopFlash() {
// Search all sublayer masks for "shine" animation and remove
layer.sublayers?.forEach {
$0.mask?.removeAnimation(forKey: "shine")
}
}
}
extension UIView {
// Helper to snapshot a view
var snapshot: UIImage? {
let renderer = UIGraphicsImageRenderer(size: bounds.size)
let image = renderer.image { context in
layer.render(in: context.cgContext)
}
return image
}
}
您可以像这样使用它:
final class ViewController: UIViewController {
let button = UIButton()
override func viewDidLoad() {
view.backgroundColor = .white
button.setTitle("My Special Button", for: .normal)
button.setTitleColor(.red, for: .normal)
button.sizeToFit()
button.addTarget(self, action: #selector(didPressButton(_:)), for: .touchUpInside)
view.addSubview(button)
let tableView = UITableView()
tableView.contentInsetAdjustmentBehavior == .never
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
button.flash()
}
@objc func didPressButton(_ sender: UIButton) {
sender.stopFlash()
}
}
您应该获得如下效果: