UIView Animation

UIView Animations

本文主要从下面五个方面进行介绍:

  1. 普通的UIView Animations
  2. Springs
  3. Transitions
  4. View Animations in Practice
  5. Keyframe Animations

Animatable properties:

  • frame
  • bounds
  • center
  • backgroundColor
  • alpha
  • transform

普通的UIView Animations

Declaration
SWIFT
class func animateWithDuration(_ duration: NSTimeInterval,
delay delay: NSTimeInterval,
options options: UIViewAnimationOptions,
animations animations: () -> Void,
completion completion: ((Bool) -> Void)?)
OBJECTIVE-C

  • (void)animateWithDuration:(NSTimeInterval)duration
    delay:(NSTimeInterval)delay
    options:(UIViewAnimationOptions)options
    animations:(void (^)(void))animations
    completion:(void (^)(BOOL finished))completion

参数名都很直白不一一解释,只着重讲一下options。
有很多options可供选择:


  • UIViewAnimationOptionCurveEaseInOut

An ease-in ease-out curve causes the animation to begin slowly, accelerate through the middle of its duration, and then slow again before completing.

  • UIViewAnimationOptionCurveEaseIn

    An ease-in curve causes the animation to begin slowly, and then speed up as it progresses.

  • UIViewAnimationOptionCurveEaseOut

    An ease-out curve causes the animation to begin quickly, and then slow as it completes.

  • UIViewAnimationOptionCurveLinear

    A linear animation curve causes an animation to occur evenly over its duration.


  • UIViewAnimationOptionRepeat

Repeat the animation indefinitely.

  • UIViewAnimationOptionAutoreverse

Run the animation backwards and forwards. Must be combined with the UIViewAnimationOptionRepeat option.


Example:

 label.textColor = UIColor.whiteColor()
 label.alpha = 0.0
 UIView.animateWithDuration(1.0, delay: 0.2, options: .CurveEaseInOut | .Repeat | .AutoReverse animations: {
        label.textColor = UIColor.yellerColor()
        label.alpha = 1.0
        }, completion: {
        })

上面例子,创造了推迟0.2秒启动的动画,动画持续时间是1.0秒。渐显label,并颜色从白到黄,达到一种闪烁的效果。因为options 设置了.Repeat, .AutoReverse。label会一直闪烁着。

Springs

Springs 可以简单理解成弹簧效果,如下图:

弹簧.png
 UIView.animateWithDuration(1.5, delay: 0.0, usingSpringWithDamping: 0.2, initialSpringVelocity: 0.0, options: [], animations: {
       self.loginButton.bounds.size.width += 80.0
     }, completion: nil)
  • usingSpringWithDamping: accept value from 0.0 to 1.0. Values closer to 0.0 create a bouncier animation, while values closer to 1.0 create a stiff-looking effect. You can think of this value as the “stiffness” of the spring.
  • initialSpringVelocity: This controls the initial velocity of the animation. A value of 1.0 sets the velocity of the animation to cover the total distance of the animation in the span of one second. Bigger and smaller values will cause the animation to have more or less velocity.
    效果如下图:


    moveSpring.png
UIView.animateWithDuration(0.33, delay: 0.0, usingSpringWithDamping: 0.7, initialSpringVelocity: 0.0, options: [], animations: {
      self.loginButton.center.y += 60.0
       self.loginButton.backgroundColor = UIColor(red: 0.85, green: 0.83, blue: 0.45, alpha: 1.0)      
       self.spinner.center = CGPoint(x: 40.0, y: self.loginButton.frame.size.height/2)
       self.spinner.alpha = 1.0 
     }, completion: nil)

Transitions

Transitions are predefined animations you can apply to views
the predefined transition animation options:

  • TransitionFlipFromLeft
  • TransitionFlipFromRight
  • TransitionCurlUp
  • TransitionCurlDown
  • TransitionCrossDissolve
  • TransitionFlipFromTop
  • TransitionFlipFromBottom

+ transitionWithView:duration:options:animations:completion:
Creates a transition animation for the specified container view.

Discussion
This method applies a transition to the specified view so that you can make state changes to it. The block you specify in the animations parameter contains whatever state changes you want to make. You can use this block to add, remove, show, or hide subviews of the specified view. If you want to incorporate other animatable changes, you must include the UIViewAnimationOptionAllowAnimatedContent key in the options parameter.

Add a new view

UIView.transitionWithView(animationContainerView, duration: 0.33, options: .CurveEaseOut | .TransitionFlipFromBottom, animations {
        self.animationContainerView.addSubview(newView)
    }, completion: nil}

Removing a view

UIView.transitionWithView(animationContainerView, duration: 0.33, options: .CurveEaseOut | .TransitionFlipFromBottom, animations: {
        self.newView.removeFromSuperview()
    }, completion: nil)

Hiding/ showing a view

UIView.transitionWithView(self.newView, duration: 0.33, options: .CurveEaseOut | .TransitionFlipFromBottom, animations: {
        self.newView.hidden = true
}, complection: nil)

Replacing a view with another view

[UIView transitionWithView:containerView
            duration:0.2
            options:UIViewAnimationOptionTransitionFlipFromLeft
            animations:^{ 
        [fromView removeFromSuperview]; 
        [containerView addSubview:toView]; 
    }
            completion:nil];

there a sampler way to implement it:

+ (void)transitionFromView:(UIView *)fromView
                     toView:(UIView *)toView
                   duration:(NSTimeInterval)duration
                    options:(UIViewAnimationOptions)options
                 completion:(void (^)(BOOL finished))completion

Discussion
This method provides a simple way to transition from the view in the fromView parameter to the view in the toView parameter. By default, the view in fromView is replaced in the view hierarchy by the view in toView. If both views are already part of your view hierarchy, you can include the UIViewAnimationOptionShowHideTransitionViews option in the options parameter to simply hide or show them.
This method modifies the views in their view hierarchy only. It does not modify your application’s view controllers in any way. For example, if you use this method to change the root view displayed by a view controller, it is your responsibility to update the view controller appropriately to handle the change.
The view transition starts immediately unless another animation is already in-flight, in which case it starts immediately after the current animation finishes.

UIView.transitonFromView(self.oldView, toView: self.newView, duration: 0.2, options: .TransitionFlipFromTop, completion: nil)

To simply hide or show them:

UIView.transitionFromView(self.oldView, toView: self.newView, duration: 0.2, options: .ShowHideTransitionViews, completion:nil)

In Practice

Crossfading animations

 func fadeImageView(imageView: UIImageView, toImage: UIImage, showEffects: Bool) {
    UIView.transitionWithView(imageView, duration: 1.0, options: .TransitionCrossDissolve, animations: {
        imageView.image = toImage
    }, complection: nil)
    UIView.animationWithDuration(1.0, delay: 0.9, options: .CurveEaseOut, animation: {
        self.snowView.alpha = showEffects ? 1.0 : 0.0
    }, completion: nil)

Cube transitions

func cubeTransition(label: UILabel, text: String, direction: AnimationDirection) {
         let auxLabel = UILabel(frame: label.frame)
         auxLabel.text = text
         auxLabel.font = label.font
         auxLabel.textAlignment = label.textAlignment
         auxLabel.textColor = label.textColor
         auxLabel.backgroundColor = UIColor.clearColor()
         
         let auxLabelOffset = CGFloat(direction.rawValue) * label.frame.size.height / 2.0
         auxLabel.transform = CGAffineTransformConcat(CGAffineTransformMakeScale(1.0, 0.1), CGAffineTransformMakeTranslation(0.0, auxLabelOffset))
         label.superview!.addSubview(auxLabel)
        
        UIView.animateWithDuration(0.5, delay: 0.0, options: .CurveEaseOut, animations: {
            auxLabel.transform = CGAffineTransformIdentity
            label.transform = CGAffineTransformConcat(
                 CGAffineTransformMakeScale(1.0, 0.1),
                 CGAffineTransformMakeTranslation(0.0, -auxLabelOffset))
             }, completion: { _ in
                 label.text = auxLabel.text
                 label.transform = CGAffineTransformIdentity
                 auxLabel.removeFromSuperview()
         })
  }

Fade and bounce transitions

 func moveLabel(label: UILabel, text: String, offset: CGPoint) {
         let auxLabel = UILabel(frame: label.frame)
         auxLabel.text = text
         auxLabel.font = label.font
         auxLabel.textAlignment = label.textAlignment
         auxLabel.textColor = label.textColor
         auxLabel.backgroundColor = UIColor.clearColor()
         
         auxLabel.transform = CGAffineTransformMakeTranslation(offset.x, offset.y)
         auxLabel.alpha = 0.0
         view.addSubview(auxLabel)
         
         UIView.animateWithDuration(0.5, delay: 0.0, options: .CurveEaseIn, animations: {
             label.transform = CGAffineTransformMakeTranslation(offset.x, offset.y)
             label.alpha = 0.0
             }, completion: nil)
         UIView.animateWithDuration(0.25, delay: 0.1, options: .CurveEaseIn, animations: {
             auxLabel.transform = CGAffineTransformIdentity
             auxLabel.alpha = 1.0
             }, completion: { _ in
        auxLabel.removeFromSuperview()
                 label.text = text
                 label.alpha = 1.0
                 label.transform = CGAffineTransformIdentity
         })
 }

Keyframe Animations

Declaration:

class func animateKeyframesWithDuration(_ duration: NSTimeInterval,
delay delay: NSTimeInterval,
options options: UIViewKeyframeAnimationOptions,
animations animations: () -> Void,
completion completion: ((Bool) -> Void)?)
OBJECTIVE-C

  • (void)animateKeyframesWithDuration:(NSTimeInterval)duration
    delay:(NSTimeInterval)delay
    options:(UIViewKeyframeAnimationOptions)options
    animations:(void (^)(void))animations
    completion:(void (^)(BOOL finished))completion
    Discussion
    This method creates an animation block that you can use to set up a keyframe-based animation. The keyframes themselves are not part of the initial animation block you create using this method. Inside the animations block, you must add the keyframe time and animation data by calling the addKeyframeWithRelativeStartTime:relativeDuration:animations: method one or more times. Adding keyframes causes the animation to animate the view from its current value to the value of the first keyframe, then to the value of the next keyframe, and so on at the times you specify.
    If you do not add any keyframes in the animations block, the animation proceeds from start to end like a standard animation block. In other words, the system animates from the current view values to any new values over the specified duration.
let originalCenter = planeImage.center
     
     UIView.animateKeyframesWithDuration(1.5, delay: 0.0, options: [], animations: {
       //add keyframes
       //
       UIView.addKeyframeWithRelativeStartTime(0.0, relativeDuration: 0.25, animations: {
         self.planeImage.center.x += 80.0
         self.planeImage.center.y -= 10.0
       })
       
       UIView.addKeyframeWithRelativeStartTime(0.1, relativeDuration: 0.4) {
         self.planeImage.transform = CGAffineTransformMakeRotation(CGFloat(-M_PI_4/2))
       }
       
       UIView.addKeyframeWithRelativeStartTime(0.25, relativeDuration: 0.25) {
         self.planeImage.center.x += 100.0
         self.planeImage.center.y -= 50.0
         self.planeImage.alpha = 0.0
       }
       
       UIView.addKeyframeWithRelativeStartTime(0.51, relativeDuration: 0.01) {
         self.planeImage.transform = CGAffineTransformIdentity
         self.planeImage.center = CGPoint(x: 0.0, y: originalCenter.y)
       }
       
       UIView.addKeyframeWithRelativeStartTime(0.55, relativeDuration: 0.45) {
         self.planeImage.alpha = 1.0
         self.planeImage.center = originalCenter
       }
       
       }, completion: nil)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容