MPTransition.m 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. //
  2. // MPTransition.m
  3. // MPPlayerDemo
  4. //
  5. // Created by Maple on 2019/12/31.
  6. // Copyright © 2019 Maple. All rights reserved.
  7. //
  8. #import "MPTransition.h"
  9. #import "MPPlayerController.h"
  10. #import <ZFUtilities.h>
  11. @interface MPTransition()
  12. @property (nonatomic, strong) UIView *startView;
  13. @property (nonatomic, strong) UIImage *startImage;
  14. @property (nonatomic, assign) NSTimeInterval duration;
  15. @property (nonatomic, strong) MPPlayerController *player;
  16. @property (nonatomic, assign) UINavigationControllerOperation operation;
  17. @property (nonatomic, assign) void(^completion)(void);
  18. @property (nonatomic, strong) UIView *effectView;
  19. @end
  20. @implementation MPTransition
  21. + (instancetype)animationWithDuration:(NSTimeInterval)duration
  22. startView:(UIView *)startView
  23. startImage:(UIImage *)startImage
  24. player: (MPPlayerController *)player
  25. operation:(UINavigationControllerOperation)operation
  26. completion:(void(^)(void))completion
  27. {
  28. MPTransition *animation = [MPTransition new];
  29. animation.player = player;
  30. animation.duration = duration;
  31. animation.startView = startView;
  32. animation.startImage = startImage;
  33. animation.operation = operation;
  34. animation.completion = completion;
  35. return animation;
  36. }
  37. - (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext {
  38. if (self.operation == UINavigationControllerOperationPush) {
  39. [self startPushAnimation: transitionContext];
  40. }else {
  41. [self startPopAnimation: transitionContext];
  42. }
  43. }
  44. - (void)startPushAnimation:(id<UIViewControllerContextTransitioning>)transitionContext
  45. {
  46. // 获取 fromView 和 toView
  47. UIView *fromView = [transitionContext viewForKey:UITransitionContextFromViewKey];
  48. UIView *toView = [transitionContext viewForKey:UITransitionContextToViewKey];
  49. // 添加到动画容器视图中
  50. [[transitionContext containerView] addSubview:fromView];
  51. [[transitionContext containerView] addSubview:toView];
  52. UIImageView *bgImgView = [[UIImageView alloc] initWithFrame:fromView.bounds];
  53. bgImgView.contentMode = UIViewContentModeScaleAspectFill;
  54. bgImgView.image = self.startImage;
  55. UIView *colorCover = [[UIView alloc] init];
  56. colorCover.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.4];
  57. colorCover.frame = fromView.bounds;
  58. [bgImgView addSubview:colorCover];
  59. [bgImgView addSubview:self.effectView];
  60. [[transitionContext containerView] addSubview:bgImgView];
  61. // 创建player容器
  62. CGRect winFrame = CGRectZero;
  63. if (self.startView) {
  64. winFrame = [self.startView convertRect:self.startView.bounds toView:nil];
  65. }
  66. UIImageView *playerContainer = [[UIImageView alloc] initWithFrame:winFrame];
  67. playerContainer.image = self.startImage;
  68. playerContainer.contentMode = UIViewContentModeScaleAspectFit;
  69. [[transitionContext containerView] addSubview:playerContainer];
  70. if (self.player) {
  71. self.player.currentPlayerManager.scalingMode = self.player.videoFlowScalingMode;
  72. self.player.currentPlayerManager.view.backgroundColor = [UIColor clearColor];
  73. [self.player updateNoramlPlayerWithContainerView:playerContainer];
  74. }
  75. CGFloat bottomOffset = iPhoneX ? 83 : 0;
  76. NSTimeInterval duration = [self transitionDuration:transitionContext];
  77. CGRect targetFrame = CGRectMake(0, 0, ZFPlayer_ScreenWidth, ZFPlayer_ScreenHeight - bottomOffset);
  78. toView.alpha = 0.0f;
  79. bgImgView.alpha = 0;
  80. [UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
  81. // mask 渐变效果
  82. bgImgView.alpha = 1;
  83. playerContainer.frame = targetFrame;
  84. } completion:^(BOOL finished) {
  85. toView.alpha = 1.0f;
  86. // 移除临时视图
  87. [bgImgView removeFromSuperview];
  88. [playerContainer removeFromSuperview];
  89. // 结束动画
  90. [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
  91. if (self.completion) {
  92. self.completion();
  93. }
  94. }];
  95. }
  96. - (void)startPopAnimation: (id<UIViewControllerContextTransitioning>)transitionContext
  97. {
  98. // 获取 fromView 和 toView
  99. UIView *fromView = [transitionContext viewForKey:UITransitionContextFromViewKey];
  100. UIView *toView = [transitionContext viewForKey:UITransitionContextToViewKey];
  101. self.player.currentPlayerManager.view.backgroundColor = [UIColor blackColor];
  102. // 添加到动画容器视图中
  103. UIView *container = [transitionContext containerView];
  104. [container addSubview:toView];
  105. [container addSubview:fromView];
  106. container.backgroundColor = [UIColor clearColor];
  107. // 添加动画临时视图到 fromView
  108. CGFloat bottomOffset = iPhoneX ? 83 : 0;
  109. CGRect normalFrame = CGRectMake(0, 0, ZFPlayer_ScreenWidth, ZFPlayer_ScreenHeight - bottomOffset);
  110. CGRect winFrame = CGRectZero;
  111. if (self.startView) {
  112. winFrame = [self.startView convertRect:self.startView.bounds toView:nil];
  113. }
  114. // 显示图片
  115. UIImageView *imageView = [[UIImageView alloc] initWithFrame:normalFrame];
  116. imageView.contentMode = UIViewContentModeScaleAspectFit;
  117. imageView.clipsToBounds = YES;
  118. imageView.image = self.startImage;
  119. if (self.player) {
  120. // pop回去的时候,设置回原来的scalingMode
  121. self.player.currentPlayerManager.scalingMode = ZFPlayerScalingModeAspectFill;
  122. [self.player updateNoramlPlayerWithContainerView:imageView];
  123. }
  124. [container addSubview:imageView];
  125. toView.alpha = 1;
  126. fromView.alpha = 1;
  127. NSTimeInterval duration = [self transitionDuration:transitionContext];
  128. [UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
  129. imageView.frame = winFrame;
  130. fromView.alpha = 0;
  131. } completion:^(BOOL finished) {
  132. // 移除临时视图
  133. [imageView removeFromSuperview];
  134. // 结束动画
  135. [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
  136. if (self.completion) {
  137. self.completion();
  138. }
  139. }];
  140. }
  141. - (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext {
  142. return self.duration;
  143. }
  144. - (UIView *)effectView {
  145. if (!_effectView) {
  146. if (@available(iOS 8.0, *)) {
  147. UIBlurEffect *effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark];
  148. _effectView = [[UIVisualEffectView alloc] initWithEffect:effect];
  149. } else {
  150. UIToolbar *effectView = [[UIToolbar alloc] init];
  151. effectView.barStyle = UIBarStyleBlackTranslucent;
  152. _effectView = effectView;
  153. }
  154. }
  155. return _effectView;
  156. }
  157. @end