swift UIView添加点击事件 & android Material Design 点击触摸水波纹扩散效果

1,426 阅读2分钟

效果图:

使用方式:UIView,UIImageView,UIButton 一样

let mView = MView()
//是否开启水波纹效果,默认开启
mView.rippleEnable = true
//设置水波纹可以扩散至view外
mView.setRippleStyle(.unbounded)

mView.onClick {
    //点击事件
    
}

UIView

import MaterialComponents

class MView :UIView {
    //水波纹效果view
    private var rippleView : MDCRippleView?
    //是否开启水波纹效果
    var rippleEnable = true
    
    var onClick :(()->())?
    
//    @objc func click(){
//        onClick?()
//    }
    
    //设置点击事件
    func onClick(todo : @escaping () ->()){
        self.onClick = todo
        
        //使用此方法设置点击事件会拦截触摸事件,无法显示水波纹效果
//        self.isUserInteractionEnabled = true
//        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.click))
//        tapGesture.numberOfTapsRequired = 1
//        self.addGestureRecognizer(tapGesture)
        
        if rippleEnable {
            //加入rippleview
            if rippleView == nil {
                rippleView = MDCRippleView(frame: self.bounds)
            }
            addSubview(rippleView!)
        }
    }
    /**
     扩散效果
     .bounded - 扩散在view内
     .unbounded - 可扩散至view外
     */
    func setRippleStyle(_ style:MDCRippleStyle){
        if rippleView == nil {
            rippleView = MDCRippleView(frame: self.bounds)
        }
        rippleView?.rippleStyle = style
    }
    /**
     触摸事件 - 开始触摸
     */
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesBegan(touches, with: event)
        if rippleEnable {
            //触摸位置
            let point = ((touches as NSSet).anyObject() as AnyObject).location(in:self)
            //设置rippleview的圆角 = 父view的圆角
            rippleView?.layer.cornerRadius = self.layer.cornerRadius
            //.unbounded 时,扩散的半径
            rippleView?.maximumRadius = sqrt(self.bounds.width*self.bounds.width + self.bounds.height*self.bounds.height)/2
            //开始扩散动画
            rippleView?.beginRippleTouchDown(at: point, animated: true, completion: nil)
        }
    }
    /**
     触摸结束
     */
    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesEnded(touches, with: event)
        if rippleEnable {
            //收回扩散
            rippleView?.beginRippleTouchUp(animated: true, completion: nil)
        }
        onClick?()
    }
    /**
     触摸取消
     */
    override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesCancelled(touches, with: event)
        if rippleEnable {
            //收回扩散
            rippleView?.beginRippleTouchUp(animated: true, completion: nil)
        }
    }
    
}

UIImageView

class MImageView :UIImageView {...同UIView

}

UIButton

import MaterialComponents

class MButton: UIButton {
    
    private var rippleView : MDCRippleView?
    
    var rippleEnable = true
    
    private var onClick :(()->())?
    
    @objc func click(){
        onClick?()
    }
    
    func onClick(todo : @escaping () ->()){
        self.onClick = todo
        //添加点击事件
        self.addTarget(self, action: #selector(self.click), for: .touchUpInside)
        //取消点击图片高亮
        adjustsImageWhenHighlighted = false
        if rippleEnable {
            if rippleView == nil {
                rippleView = MDCRippleView(frame: self.bounds)
            }
            addSubview(rippleView!)
        }
    }
    
    
    func setRippleStyle(_ style:MDCRippleStyle){
        if rippleView == nil {
            rippleView = MDCRippleView(frame: self.bounds)
        }
        rippleView?.rippleStyle = style
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesBegan(touches, with: event)
        if rippleEnable {
            let point = ((touches as NSSet).anyObject() as AnyObject).location(in:self)
            rippleView?.layer.cornerRadius = self.layer.cornerRadius
            rippleView?.maximumRadius = sqrt(self.bounds.width*self.bounds.width + self.bounds.height*self.bounds.height)/2
            rippleView?.beginRippleTouchDown(at: point, animated: true, completion: nil)
        }
    }
    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesEnded(touches, with: event)
        if rippleEnable {
            rippleView?.beginRippleTouchUp(animated: true, completion: nil)
        }
    }
    override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesCancelled(touches, with: event)
        if rippleEnable {
            rippleView?.beginRippleTouchUp(animated: true, completion: nil)
        }
    }
}

水波纹效果开源库 点击这里

同理,cell中同样可以使用,以UICollectionViewCell为例,代码如下:

UICollectionViewCell

import MaterialComponents

class MCollectionViewCell: UICollectionViewCell {
    private var rippleView : MDCRippleView!
    //是否开启水波纹效果
    var rippleEnable = true
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        //加入view
        rippleView = MDCRippleView(frame: bounds)
        addSubview(rippleView)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    //设置要显示水波纹效果的view,不设置的话默认扩散至整个cell
    func setRippleView(_ view:UIView){
        rippleView.frame = view.bounds
        view.addSubview(rippleView)
    }
    //触摸事件
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesBegan(touches, with: event)
        if rippleEnable {
            let point = ((touches as NSSet).anyObject() as AnyObject).location(in:self)
            rippleView?.beginRippleTouchDown(at: point, animated: true, completion: nil)
        }
    }
    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesEnded(touches, with: event)
        if rippleEnable {
            rippleView?.beginRippleTouchUp(animated: true, completion: nil)
        }
    }
    override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesCancelled(touches, with: event)
        if rippleEnable {
            rippleView?.beginRippleTouchUp(animated: true, completion: nil)
        }
    }
}