MST

星途 面试题库

面试题:Objective-C 在 iOS 界面设计中如何实现视图的动画过渡

请描述在 Objective-C 开发 iOS 应用时,使用何种方式能实现视图之间平滑的动画过渡,例如淡入淡出、滑动切换等,并给出简单代码示例。
32.8万 热度难度
编程语言Objective-C

知识考点

AI 面试

面试题答案

一键面试

实现方式

  1. 使用 UIView 的动画方法UIView 提供了一系列类方法来创建动画,能够方便地实现视图的淡入淡出、滑动切换等效果。
  2. 使用 UIViewController 的转场动画:可以通过自定义 UIViewControllerAnimatedTransitioning 协议来实现更复杂的视图控制器之间的过渡动画。
  3. 使用 CAAnimation 及其子类Core Animation 框架提供了更底层的动画控制,例如 CABasicAnimationCAKeyframeAnimation 等,可以实现各种复杂的动画效果。

代码示例 - 使用 UIView 的动画方法

  1. 淡入淡出效果
// 淡入
UIView *viewToFadeIn = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 200, 200)];
viewToFadeIn.backgroundColor = [UIColor redColor];
[self.view addSubview:viewToFadeIn];
viewToFadeIn.alpha = 0.0;
[UIView animateWithDuration:1.0 animations:^{
    viewToFadeIn.alpha = 1.0;
}];

// 淡出
[UIView animateWithDuration:1.0 animations:^{
    viewToFadeIn.alpha = 0.0;
} completion:^(BOOL finished) {
    [viewToFadeIn removeFromSuperview];
}];
  1. 滑动切换效果(以从右向左滑动为例)
UIView *viewToSlide = [[UIView alloc] initWithFrame:CGRectMake(self.view.bounds.size.width, 0, self.view.bounds.size.width, self.view.bounds.size.height)];
viewToSlide.backgroundColor = [UIColor blueColor];
[self.view addSubview:viewToSlide];
[UIView animateWithDuration:1.0 animations:^{
    viewToSlide.frame = CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height);
}];

代码示例 - 使用 UIViewController 的转场动画

  1. 定义一个实现 UIViewControllerAnimatedTransitioning 协议的类
#import <UIKit/UIKit.h>

@interface SlideTransitionAnimator : NSObject <UIViewControllerAnimatedTransitioning>

@property (nonatomic, assign) BOOL isPresenting;

@end

@implementation SlideTransitionAnimator

- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext {
    return 0.5;
}

- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext {
    UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    UIView *containerView = [transitionContext containerView];

    CGRect screenBounds = [UIScreen mainScreen].bounds;
    if (self.isPresenting) {
        toVC.view.frame = CGRectMake(screenBounds.size.width, 0, screenBounds.size.width, screenBounds.size.height);
        [containerView addSubview:toVC.view];
    } else {
        fromVC.view.frame = CGRectMake(0, 0, screenBounds.size.width, screenBounds.size.height);
        [containerView insertSubview:toVC.view belowSubview:fromVC.view];
    }

    [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
        if (self.isPresenting) {
            toVC.view.frame = CGRectMake(0, 0, screenBounds.size.width, screenBounds.size.height);
        } else {
            fromVC.view.frame = CGRectMake(-screenBounds.size.width, 0, screenBounds.size.width, screenBounds.size.height);
        }
    } completion:^(BOOL finished) {
        [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
    }];
}

@end
  1. 在视图控制器中使用该转场动画
#import "ViewController.h"
#import "SlideTransitionAnimator.h"

@interface ViewController () <UIViewControllerTransitioningDelegate>

@property (nonatomic, strong) SlideTransitionAnimator *animator;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.animator = [[SlideTransitionAnimator alloc] init];
    UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
    button.frame = CGRectMake(100, 100, 200, 50);
    [button setTitle:@"Present" forState:UIControlStateNormal];
    [button addTarget:self action:@selector(presentViewController:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:button];
}

- (void)presentViewController:(UIButton *)sender {
    UIViewController *vc = [[UIViewController alloc] init];
    vc.view.backgroundColor = [UIColor greenColor];
    self.animator.isPresenting = YES;
    vc.transitioningDelegate = self;
    [self presentViewController:vc animated:YES completion:nil];
}

- (id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source {
    self.animator.isPresenting = YES;
    return self.animator;
}

- (id <UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed {
    self.animator.isPresenting = NO;
    return self.animator;
}

@end

代码示例 - 使用 CAAnimation 及其子类

  1. 淡入淡出效果使用 CABasicAnimation
UIView *viewForCAAnimation = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 200, 200)];
viewForCAAnimation.backgroundColor = [UIColor yellowColor];
[self.view addSubview:viewForCAAnimation];

CABasicAnimation *fadeAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
fadeAnimation.fromValue = @(0.0);
fadeAnimation.toValue = @(1.0);
fadeAnimation.duration = 1.0;
[viewForCAAnimation.layer addAnimation:fadeAnimation forKey:@"fadeIn"];
  1. 滑动切换效果使用 CAKeyframeAnimation(以从下向上滑动为例)
UIView *viewToSlideWithCA = [[UIView alloc] initWithFrame:CGRectMake(0, self.view.bounds.size.height, self.view.bounds.size.width, self.view.bounds.size.height)];
viewToSlideWithCA.backgroundColor = [UIColor purpleColor];
[self.view addSubview:viewToSlideWithCA];

CAKeyframeAnimation *slideAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position.y"];
NSValue *startValue = [NSValue valueWithCGPoint:CGPointMake(viewToSlideWithCA.center.x, self.view.bounds.size.height + viewToSlideWithCA.bounds.size.height / 2)];
NSValue *endValue = [NSValue valueWithCGPoint:CGPointMake(viewToSlideWithCA.center.x, viewToSlideWithCA.center.y)];
slideAnimation.values = @[startValue, endValue];
slideAnimation.duration = 1.0;
[viewToSlideWithCA.layer addAnimation:slideAnimation forKey:@"slideUp"];