简体   繁体   English

UICollectionView单元的材质纹波效果

[英]Material Ripple Effect for UICollectionView Cell

I am trying to create a material ripple effect for a UICollectioView cell. 我正在尝试为UICollectioView单元创建材质波纹效果。 For Android, there are several material design options to do so, but for iOS that does not appear to be the case. 对于Android,可以使用多种材料设计选项,但对于iOS似乎并非如此。 Below is my custom cell I am using as the prototype to populate the UICollectioView: 以下是我用作模板填充UICollectioView的自定义单元格:

import UIKit

class PollCell: UICollectionViewCell {


    @IBOutlet weak var imageView: UIImageView!

    @IBOutlet weak var pollQuestion: UILabel!

}

Where I initialize the CollectioViewCell: 我在哪里初始化CollectioViewCell:

    override func viewDidLoad() {
    super.viewDidLoad()

    ref = FIRDatabase.database().reference()
    prepareMenuButton()


    // Uncomment the following line to preserve selection between presentations
    // self.clearsSelectionOnViewWillAppear = false

    // Register cell classes

    self.dataSource = self.collectionView?.bind(to: self.ref.child("Polls")) { collectionView, indexPath, snap in
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! PollCell
        //Here is where I am having issues
        cell.pulseAnimation
        /* populate cell */
        cell.pollQuestion.text = snap.childSnapshot(forPath: "question").value as! String?
        let urlPollImage = snap.childSnapshot(forPath: "image_URL").value as! String?

        cell.imageView.sd_setImage(with: URL(string: urlPollImage!), placeholderImage: UIImage(named: "Fan_Polls_Logo.png"))
        //Comment
        return cell
    }

Here is an image of one of the cells on a device: 这是设备上一个单元的图像:

在此处输入图片说明

Use a CATransition 使用CATransition

func ripple(view:UIView){
    let ripple = CATransition()
    ripple.type = "rippleEffect"
    ripple.duration = 0.5
    view.layer.add(ripple, forKey: nil)
}

you can pass whatever you want to ripple and it will. 您可以传递任何您想要波动的东西,它会。 Example

self.ripple(view: imageView)

or you could pass the cell itself on didselect,touches began or whatever you are using to trigger the ripple. 或者您可以通过单元格本身进行didselect操作,触摸开始或您用来触发纹波的任何方法。

But based on what you are telling me you want a circular pulse to cover the view so I tried this. 但是根据您告诉我的内容,您想要一个圆形脉冲来覆盖视图,因此我尝试了此操作。 I put some libraries to consider in the comments but here is my quick attempt at what you are wanting. 我在评论中加入了一些库,但在这里您可以快速尝试一下。

var scaleFactor : CGFloat = 0.6
    var animationColor : UIColor = UIColor.green
    var animationDuration : Double = 0.4
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {.  
        super.touchesBegan(touches, with: event)
        let coverView = UIView(frame: bounds)
        coverView.autoresizingMask = [.flexibleWidth,.flexibleHeight]
        coverView.backgroundColor = UIColor.clear
        self.addSubview(coverView)

        let touch = touches.first!
        let point = touch.location(in: self)

        let ourTouchView = UIView(frame: CGRect(x: point.x - 5, y: point.y - 5, width: 10, height: 10))
        print(ourTouchView)
        print(point)


        let circleMaskPathInitial = UIBezierPath(ovalIn: ourTouchView.frame)
        let radius = max((self.bounds.width * scaleFactor) , (self.bounds.height * scaleFactor))
        let circleMaskPathFinal = UIBezierPath(ovalIn: ourTouchView.frame.insetBy(dx: -radius, dy: -radius))


        let rippleLayer = CAShapeLayer()
        rippleLayer.opacity = 0.4
        rippleLayer.fillColor = animationColor.cgColor
        rippleLayer.path = circleMaskPathFinal.cgPath
        coverView.layer.addSublayer(rippleLayer)

        //fade up
        let fadeUp = CABasicAnimation(keyPath: "opacity")
        fadeUp.beginTime = CACurrentMediaTime()
        fadeUp.duration = animationDuration * 0.6
        fadeUp.toValue = 0.6
        fadeUp.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
        fadeUp.fillMode = kCAFillModeForwards
        fadeUp.isRemovedOnCompletion = false
        rippleLayer.add(fadeUp, forKey: nil)

        //fade down
        let fade = CABasicAnimation(keyPath: "opacity")
        fade.beginTime = CACurrentMediaTime() + animationDuration * 0.60
        fade.duration = animationDuration * 0.40
        fade.toValue = 0
        fade.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
        fade.fillMode = kCAFillModeForwards
        fade.isRemovedOnCompletion = false
        rippleLayer.add(fade, forKey: nil)

        //change path
        CATransaction.begin()
        let maskLayerAnimation = CABasicAnimation(keyPath: "path")
        maskLayerAnimation.fromValue = circleMaskPathInitial.cgPath
        maskLayerAnimation.toValue = circleMaskPathFinal.cgPath
        maskLayerAnimation.beginTime = CACurrentMediaTime()
        maskLayerAnimation.duration = animationDuration
        maskLayerAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
        CATransaction.setCompletionBlock({
            coverView.removeFromSuperview()
        })
        rippleLayer.add(maskLayerAnimation, forKey: "path")
        CATransaction.commit()
    }

I probably would not execute this in touches began and instead use a tap gesture but you could do this. 我可能不会在开始触摸时执行此操作,而是使用轻击手势,但是您可以执行此操作。

If you use Material it has a CollectionViewCell that has the pulse animation built in. You can set it with the pulseAnimation property. 如果使用Material,则它将具有一个CollectionViewCell ,它内置了脉冲动画。您可以使用pulseAnimation属性进行设置。 Hope this helps. 希望这可以帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM