iOS中UIView的动画

UIView本身对于基本动画和关键帧动画、转场动画都有相应的封装,在对动画细节没有特殊要求的情况下使用起来也要简单的多。可以说在日常开发中90%以上的情况使用UIView的动画封装方法都可以搞定.

常见动画设置方法

//标记动画的开始
open class func beginAnimations(_ animationID: String?, context: UnsafeMutableRawPointer?)
//提交动画
open class func commitAnimations()

//设置动画代理对象,当动画开始或者结束时会发消息给代理对象 
open class func setAnimationDelegate(_ delegate: Any?)

//当动画即将开始时,执行delegate对象的selector,并且把beginAnimations:context:中传入的参数传进selector 
open class func setAnimationWillStart(_ selector: Selector?)

//当动画结束时,执行delegate对象的selector,并且把beginAnimations:context:中传入的参数传进selector 
open class func setAnimationDidStop(_ selector: Selector?)

//动画的持续时间,秒为单位 
open class func setAnimationDuration(_ duration: TimeInterval)

//动画延迟delay秒后再开始 
open class func setAnimationDelay(_ delay: TimeInterval)

//动画的开始时间,默认为now 
open class func setAnimationStart(_ startDate: Date)

//动画的时间变化类型 
 open class func setAnimationCurve(_ curve: UIView.AnimationCurve)

//动画的重复次数 
open class func setAnimationRepeatCount(_ repeatCount: Float)

//如果设置为YES,代表动画每次重复执行的效果会跟上一次相反 
open class func setAnimationRepeatAutoreverses(_ repeatAutoreverses: Bool)

//设置视图view的过渡效果, transition指定过渡类型, cache设置YES代表使用视图缓存,性能较好. 
open class func setAnimationTransition(_ transition: UIView.AnimationTransition, for view: UIView, cache: Bool)

//是否允许动画
open class func setAnimationsEnabled(_ enabled: Bool)

可动画属性

  • bounds: Animate this property to reposition the view’s content within the view’s frame.
  • frame: Animate this property to move and/or scale the view.
  • center: Animate this property when you want to move the view to a new location on screen.
  • backgroundColor: Change this property of a view to have UIKit gradually change the tint of the background color over time.
  • alpha: Change this property to create fade-in and fade-out effects.
  • transform: Modify this property within an animation block to animate the rotation, scale, and/or position of a view.

动画的方式

1、使用必包方式

 UIView.animate(withDuration: 1, animations: {
      // animate code
 }, completion: { finished in
      // animation finished
 })

2、使用begin和commit方式

UIView.beginAnimations("animate", context: nil)
UIView.setAnimationDuration(0.5)
animationView.backgroundColor = UIColor.cyan
UIView.commitAnimations()

动画的类型

基本动画

使用UIView进行动画非常简单,iOS 提供了很方便的函数

extension UIView {
@available(iOS 4.0, *)
open class func animate(withDuration duration: TimeInterval,
                        delay: TimeInterval,
                        options: UIViewAnimationOptions = [],
                        animations: @escaping () -> Swift.Void,
                        completion: ((Bool) -> Swift.Void)? = nil)

@available(iOS 4.0, *)
open class func animate(withDuration duration: TimeInterval,
                        animations: @escaping () -> Swift.Void,
                        completion: ((Bool) -> Swift.Void)? = nil) // delay = 0.0, options = 0

@available(iOS 4.0, *)
open class func animate(withDuration duration: TimeInterval,
                        animations: @escaping () -> Swift.Void) // delay = 0.0, options = 0, completion = NULL
}

duration:动画的持续时间
delay:延迟动画时间
options:动画进行的方式,不同的选项直接可以通过“与”操作进行合并,同时使用,可以分为两类:

控制速度:

//动画先缓慢,然后逐渐加速,再变慢
public static var curveEaseInOut: UIViewAnimationOptions { get } //default 
//
public static var curveEaseIn: UIViewAnimationOptions { get }
//动画开始快,后面慢
public static var curveEaseOut: UIViewAnimationOptions { get }
//动画匀速执行
public static var curveLinear: UIViewAnimationOptions { get }

如图所示

4010043-91de89b45c0b810f.gif

控制过程:

public static var allowUserInteraction: UIViewAnimationOptions { get } // turn on user interaction while animating
public static var beginFromCurrentState: UIViewAnimationOptions { get } // start all views from current value, not initial value
public static var `repeat`: UIViewAnimationOptions { get } // repeat animation indefinitely
public static var autoreverse: UIViewAnimationOptions { get } // if repeat, run animation back and forth

animations:动画闭包,在 animations中对 UIView 的属性进行动画
completion:动画完成闭包

移动图片

实现一个简单的需求,点击屏幕移动图片

闭包方式

class UIViewAnimationController: UIViewController {
    lazy var imageView: UIImageView = {
        let imageV = UIImageView(image: UIImage(named: "man"))
        return imageV
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = UIColor.white

        view.addSubview(imageView)
        imageView.center = view.center
    }

    override func touchesBegan(_ touches: Set, with event: UIEvent?) {
        let touch = touches.first!
        let location = touch.location(in: view)
        // 根据需求选择对应的方法设置对应的属性
        UIView.animate(withDuration: 0.5) {
            self.imageView.center = location
        }
    }
}

提交动画方式

override func touchesBegan(_ touches: Set, with event: UIEvent?) {
        let touch = touches.first!
        let location = touch.location(in: view)
        // 根据需求设置相应属性
        UIView.beginAnimations(nil, context: nil)
        UIView.setAnimationDuration(0.5)
        self.imageView.center = location
        UIView.commitAnimations()
    }

效果如下

iOS中UIView的动画_第1张图片
move.2018-11-16 18_53_21.gif

关键帧动画

有些时候我们需要自己设定若干关键帧,实现更复杂的动画效果,这时候就需要关键帧动画的支持了

extension UIView {

  @available(iOS 7.0, *)
  open class func animateKeyframes(withDuration duration: TimeInterval,
                                 delay: TimeInterval,
                                 options: UIViewKeyframeAnimationOptions = [],
                                 animations: @escaping () -> Swift.Void,
                                 completion: ((Bool) -> Swift.Void)? = nil)

  // start time and duration are values between 0.0 and 1.0 specifying time and duration
 //  relative to the overall time of the keyframe animation
  @available(iOS 7.0, *)
  open class func addKeyframe(withRelativeStartTime frameStartTime: Double,
                            relativeDuration frameDuration: Double,
                            animations: @escaping () -> Swift.Void)
}

同样是一张图片显示在界面上,点击界面触发关键帧动画。实现如下,会按照设置的时间进行动画

override func touchesBegan(_ touches: Set, with event: UIEvent?) {
      UIView.animateKeyframes(withDuration: 5.0, delay: 0.0, options: .calculationModeLinear, animations: {
           UIView.addKeyframe(withRelativeStartTime: 0.0, //相对于5秒所开始的时间(第0秒开始动画)
                              relativeDuration: 0.5,  //相对于5秒所持续时间(也就是5.0*0.5=2.5秒)
                              animations: {
                              self.imageView.center = CGPoint(x: 100, y: 220)
            })

           UIView.addKeyframe(withRelativeStartTime: 0.5,  //相对于5秒所持续时间(也就是5.0*0.5=2.5秒)
                              relativeDuration: 0.25, //相对于5秒所持续时间(持续5.0*0.25=1.25秒)
                              animations: {
                              self.imageView.center = CGPoint(x: 60, y: 300)
            })

           UIView.addKeyframe(withRelativeStartTime: 0.75,  //相对于5秒所开始的时间(从0.75*5.0秒开始)
                              relativeDuration: 0.25, //相对于5秒所持续时间(持续5.0*0.25=1.25秒)
                              animations: {
                              self.imageView.center = CGPoint(x: 120, y: 440)
          })
      }, completion: { finished in
            print("animation finished")
      })
}

过渡动画

过渡动画API

@available(iOS 4.0, *)
open class func transition(with view: UIView,
                       duration: TimeInterval,
                       options: UIViewAnimationOptions = [],
                       animations: (() -> Swift.Void)?,
                       completion: ((Bool) -> Swift.Void)? = nil)

// toView added to fromView.superview, fromView removed from its superview
@available(iOS 4.0, *)
open class func transition(from fromView: UIView,
                       to toView: UIView,
                       duration: TimeInterval,
                       options: UIViewAnimationOptions = [],
                       completion: ((Bool) -> Swift.Void)? = nil)

转场类型(仅适用于转场动画设置,可以从中选择一个进行设置,基本动画、关键帧动画不需要设置)

UIViewAnimationOptionTransitionNone:没有转场动画效果。
UIViewAnimationOptionTransitionFlipFromLeft :从左侧翻转效果。
UIViewAnimationOptionTransitionFlipFromRight:从右侧翻转效果。
UIViewAnimationOptionTransitionCurlUp:向后翻页的动画过渡效果。
UIViewAnimationOptionTransitionCurlDown :向前翻页的动画过渡效果。
UIViewAnimationOptionTransitionCrossDissolve:旧视图溶解消失显示下一个新视图的效果。
UIViewAnimationOptionTransitionFlipFromTop :从上方翻转效果。
UIViewAnimationOptionTransitionFlipFromBottom:从底部翻转效果。

单视图的转场动画

点击屏幕切换头像

  lazy var imageView: UIImageView = {
        let imageV = UIImageView(image: UIImage(named: "man"))
        return imageV
    }()
    var images = ["1","2","3","4","man"]

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = UIColor.white

        view.addSubview(imageView)
        imageView.center = view.center
    }

    override func touchesBegan(_ touches: Set, with event: UIEvent?) {
        UIView.transition(with: imageView, duration: 1.0, options: .transitionCrossDissolve, animations: {
            let random = arc4random_uniform(UInt32(self.images.count))
            self.imageView.image = UIImage(named: self.images[Int(random)])
        }, completion: nil)
    }

效果如下

iOS中UIView的动画_第2张图片
tran.2018-11-16 19_19_17.gif

双视图转场动画

简单实现视图之间的切换

class ViewTransitionController: UIViewController {

    lazy var subView1: UIView = {
        let view = UIView(frame: self.view.bounds)
        view.backgroundColor = UIColor.red
        return view
    }()

    lazy var subView2: UIView = {
        let view = UIView(frame: self.view.bounds)
        view.backgroundColor = UIColor.blue
        return view
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        view.addSubview(subView1)
    }

    override func touchesBegan(_ touches: Set, with event: UIEvent?) {
        var toView: UIView?
        var fromView: UIView?

        if subView1.superview == nil {
            toView = subView1
            fromView = subView2
        } else {
            toView = subView2
            fromView = subView1
        }

        UIView.transition(from: fromView!, to: toView!, duration: 1.0, options: .transitionFlipFromLeft) { finished in
            print("subView1:\(self.subView1.superview) subView2: \(self.subView2.superview)")
        }
    }
}

效果如下

iOS中UIView的动画_第3张图片
transition.2018-11-17 11_00_02.gif

弹性动画

@available(iOS 7.0, *)
open class func animate(withDuration duration: TimeInterval,
                        delay: TimeInterval,
                        usingSpringWithDamping dampingRatio: CGFloat,
                        initialSpringVelocity velocity: CGFloat,
                        options: UIView.AnimationOptions = [],
                        animations: @escaping () -> Void,
                        completion: ((Bool) -> Void)? = nil)
  • springDamping

弹性阻尼,取值范围时 0 到 1,越接近 0 ,动画的弹性效果就越明显;如果设置为 1,则动画不会有弹性效果

  • initialSpringVelocity

数值越小,动力越小,弹簧的拉伸幅度就越小。反之相反。比如:总共的动画运行距离是200 pt,你希望每秒 100pt 时,值为 0.5;

在 initialSpringVelocity 为 0 ,damping 分别为 0.4,0.6,0.8 的情况下效果如图,可见阻尼越小,弹簧效果越明显

iOS中UIView的动画_第4张图片
2018-11-17 11-54-56.2018-11-17 11_55_12.gif

你可能感兴趣的:(iOS中UIView的动画)