swift3自定义UIBotton(带动画效果)

效果

上代码

//
//  TGAnimationButton.swift
//  TGAnimationButton
//
//  Created by targetcloud on 2017/8/18.
//  Copyright © 2017年 targetcloud. All rights reserved.
//

import UIKit

enum TGAnimationButtonKind {
    case topToBottom
    case bottomToTop
    case leftToRight
    case rightToLeft
    case scale
}

class TGAnimationButton: UIButton {
    var animationKind: TGAnimationButtonKind = .topToBottom
    
    var borderColor: UIColor = UIColor.clear {
        didSet {
            layer.borderColor = borderColor.cgColor
        }
    }
    
    var borderWidth: CGFloat = 0 {
        didSet {
            layer.borderWidth = borderWidth
        }
    }
    
    var cornerRadius: CGFloat = 0 {
        didSet {
            layer.cornerRadius = cornerRadius
        }
    }
    
    public override var isEnabled: Bool {
        didSet {
            if oldValue != isEnabled {
                if oldValue {
                    lastDisabledTitle = title(for: .disabled)
                    loading(title: lastDisabledTitle)
                    setTitle("", for: .disabled)
                } else {
                    reset()
                    setTitle(lastDisabledTitle, for: .disabled)
                }
            }
        }
    }
    
    lazy var backV = UIView()
    lazy var messageLbl = UILabel()
    lazy var indicatorV: UIActivityIndicatorView = {
        let indicator = UIActivityIndicatorView()
        indicator.hidesWhenStopped = true
        indicator.sizeToFit()
        indicator.transform = CGAffineTransform(scaleX: 0.6, y: 0.6)
        return indicator
    }()
    private var lastTitle: String?
    private var lastDisabledTitle: String?
    private var lastWidth: CGFloat?
    private var lsatHeight: CGFloat?
    private let margin: CGFloat = 8
    
    private var transformY: CGFloat {
        return self.h * (animationKind == .topToBottom ? (-1) : (animationKind == .bottomToTop ? 1 : 0))
    }
    
    private var transformX: CGFloat {
        return self.w * (animationKind == .leftToRight ? (-1) : (animationKind == .rightToLeft ? 1 : 0))
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        setup()
    }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setup()
    }
    
    private func setup() {
        layer.masksToBounds = true
        
        messageLbl.textColor = titleLabel?.textColor
        messageLbl.font = titleLabel?.font
        backV.addSubview(messageLbl)
        
        indicatorV.activityIndicatorViewStyle = .gray
        backV.addSubview(indicatorV)
        
        backV.h = self.h
        backV.centerY = self.h * 0.5
        backV.backgroundColor = .clear
        backV.alpha = 0
        
        addSubview(backV)
        
        lastTitle = currentTitle
        lsatHeight = self.h
        lastWidth = self.w
    }
    
    private func loading(title: String?) {
        messageLbl.text = title
        messageLbl.textColor = self.titleColor(for: .disabled)
        messageLbl.shadowColor = self.titleShadowColor(for: .disabled)
        messageLbl.font = self.titleLabel?.font
        messageLbl.sizeToFit()
        
        indicatorV.centerY = backV.centerY
        indicatorV.x = margin
        messageLbl.centerY = indicatorV.centerY
        messageLbl.left = indicatorV.right + margin
        backV.right = messageLbl.right
        backV.w = messageLbl.right + margin
        self.w = self.w < backV.w ? backV.w : self.w
        backV.left = (self.w - backV.w ) * 0.5
        
        indicatorV.startAnimating()
        backV.transform = (title == lastTitle) ? .identity : animationKind == .scale ? CGAffineTransform(scaleX: 0.5, y: 0.5) : CGAffineTransform(translationX: transformX, y: transformY)
        UIView.animate(withDuration: 0.5) {
            self.titleLabel!.alpha = 0
            self.backV.alpha = 1
            self.backV.transform = .identity
        }
    }
    
    private func reset() {
        UIView.animate(withDuration: 0.5, animations: {
            self.titleLabel!.alpha = 1
            self.backV.alpha = 0
            self.backV.transform = (self.currentTitle == self.lastDisabledTitle) ? .identity : self.animationKind == .scale ? CGAffineTransform(scaleX: 0.5, y: 0.5) : CGAffineTransform(translationX: 0, y: self.transformY)
        }) { (finished) in
            self.backV.transform = .identity
            self.indicatorV.stopAnimating()
            UIView.animate(withDuration: 0.5, animations: {
                if self.currentTitle == self.lastDisabledTitle {
                    self.w = self.lastWidth ?? self.w
                }else{
                    self.sizeToFit()
                    self.w = self.w > (self.lastWidth ?? self.w) ? self.w : (self.lastWidth ?? self.w)
                    self.h = self.lsatHeight ?? self.h
                }
            })
        }
    }

}


//
//  UIView+extension.swift
//  TGAnimationButton
//
//  Created by targetcloud on 2017/8/18.
//  Copyright © 2017年 targetcloud. All rights reserved.
//

import UIKit

extension UIView {
    func clipRectCorner(direction: UIRectCorner, cornerRadius: CGFloat) {
        let cornerSize = CGSize(width: cornerRadius, height: cornerRadius)
        let maskPath = UIBezierPath(roundedRect: bounds, byRoundingCorners: direction, cornerRadii: cornerSize)
        let maskLayer = CAShapeLayer()
        maskLayer.frame = bounds
        maskLayer.path = maskPath.cgPath
        layer.addSublayer(maskLayer)
        layer.mask = maskLayer
    }
    
    public var x: CGFloat{
        get{
            return self.frame.origin.x
        }
        set{
            var r = self.frame
            r.origin.x = newValue
            self.frame = r
        }
    }
    
    public var left: CGFloat{
        get{
            return self.frame.origin.x
        }
        set{
            var r = self.frame
            r.origin.x = newValue
            self.frame = r
        }
    }
    
    public var y: CGFloat{
        get{
            return self.frame.origin.y
        }
        set{
            var r = self.frame
            r.origin.y = newValue
            self.frame = r
        }
    }
    
    public var rightX: CGFloat{
        get{
            return self.x + self.width
        }
        set{
            var r = self.frame
            r.origin.x = newValue - frame.size.width
            self.frame = r
        }
    }
    
    public var right: CGFloat{
        get{
            return self.x + self.width
        }
        set{
            var r = self.frame
            r.origin.x = newValue - frame.size.width
            self.frame = r
        }
    }
    
    public var bottomY: CGFloat{
        get{
            return self.y + self.height
        }
        set{
            var r = self.frame
            r.origin.y = newValue - frame.size.height
            self.frame = r
        }
    }
    
    public var bottom: CGFloat{
        get{
            return self.y + self.height
        }
        set{
            var r = self.frame
            r.origin.y = newValue - frame.size.height
            self.frame = r
        }
    }
    
    public var centerX : CGFloat{
        get{
            return self.center.x
        }
        set{
            self.center = CGPoint(x: newValue, y: self.center.y)
        }
    }
    
    public var centerY : CGFloat{
        get{
            return self.center.y
        }
        set{
            self.center = CGPoint(x: self.center.x, y: newValue)
        }
    }
    
    public var width: CGFloat{
        get{
            return self.frame.size.width
        }
        set{
            var r = self.frame
            r.size.width = newValue
            self.frame = r
        }
    }
    
    public var w: CGFloat{
        get{
            return self.frame.size.width
        }
        set{
            var r = self.frame
            r.size.width = newValue
            self.frame = r
        }
    }
    
    public var height: CGFloat{
        get{
            return self.frame.size.height
        }
        set{
            var r = self.frame
            r.size.height = newValue
            self.frame = r
        }
    }
    
    public var h: CGFloat{
        get{
            return self.frame.size.height
        }
        set{
            var r = self.frame
            r.size.height = newValue
            self.frame = r
        }
    }
    
    public var origin: CGPoint{
        get{
            return self.frame.origin
        }
        set{
            self.x = newValue.x
            self.y = newValue.y
        }
    }
    
    public var size: CGSize{
        get{
            return self.frame.size
        }
        set{
            self.width = newValue.width
            self.height = newValue.height
        }
    }
}

使用

//
//  ViewController.swift
//  TGAnimationButton
//
//  Created by targetcloud on 2017/8/18.
//  Copyright © 2017年 targetcloud. All rights reserved.
//

import UIKit

class ViewController: UIViewController {
    
    private lazy var loginButton: TGAnimationButton = {
        let btn = TGAnimationButton(frame: CGRect(x: 50, y: 50, width: 80, height: 50))
        btn.backgroundColor = UIColor.green.withAlphaComponent(0.5)
        btn.titleLabel?.font = UIFont.systemFont(ofSize: 15)
        btn.setTitleColor(.darkGray, for: .normal)
        btn.setTitleColor(.darkGray, for: .disabled)
        btn.cornerRadius = 5
        btn.borderColor = .darkGray
        btn.borderWidth = 1
        
        btn.animationKind = .scale
        btn.setTitle("登录", for: .normal)
        btn.setTitle("登录中...", for: .disabled)
        
        btn.addTarget(self, action: #selector(click), for: .touchUpInside)
        return btn
    }()
    
    func click() {
        loginButton.isEnabled = false
        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 3.0) {
            self.loginButton.isEnabled = true
            //self.loginButton.setTitle("登陆成功了了了了了了了了了了了了了了了了", for: .normal)
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.view.addSubview(loginButton)
        
    }

}




你可能感兴趣的:(swift3)