Material Ripple Effect for UICollectionView Cell

↘锁芯ラ 提交于 2019-12-24 09:07:05

问题


I am trying to create a material ripple effect for a UICollectioView cell. For Android, there are several material design options to do so, but for iOS that does not appear to be the case. Below is my custom cell I am using as the prototype to populate the UICollectioView:

import UIKit

class PollCell: UICollectionViewCell {


    @IBOutlet weak var imageView: UIImageView!

    @IBOutlet weak var pollQuestion: UILabel!

}

Where I initialize the 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:


回答1:


If you use Material it has a CollectionViewCell that has the pulse animation built in. You can set it with the pulseAnimation property. Hope this helps.




回答2:


Use a 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.

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.



来源:https://stackoverflow.com/questions/42710083/material-ripple-effect-for-uicollectionview-cell

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!