欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

播放器横竖屏方案

程序员文章站 2022-06-15 12:38:46
类似现在主流app的横竖切换的方式原理 : 在播放器横屏时候, present一个新的视图控制器, 并在该新控制器中支持横竖屏. dismiss时候, 返回之前的播放器;源码 :// - 声明#import #pragma mark - 横屏的控制器@interface DYVideoPlayerVC : UIViewController/** 初始化方法 */- (instancetype)initWithVideoPlayerView:(...

类似现在主流app的横竖切换的方式

  1. 原理 : 在播放器横屏时候, present一个新的视图控制器, 并在该新控制器中支持横竖屏. dismiss时候, 返回之前的播放器;
  2. 源码 :

// - 声明

#import <UIKit/UIKit.h>
#import "DYVideoPlayerView+Private.h"

#pragma mark - 横屏的控制器
@interface DYVideoPlayerVC : UIViewController

/** 初始化方法 */
- (instancetype)initWithVideoPlayerView:(UIView *)videoPlayerView preferredInterfaceOrientationForPresentation:(UIInterfaceOrientation)orientation;

@end

#pragma mark - 跳转横屏控制器的转场动画
typedef NS_ENUM(NSUInteger, DYVideoPlayerTransitionType){
    DYVideoPlayerTransitionTypePresent = 0,
    DYVideoPlayerTransitionTypeDismiss,
};

@interface DYVideoPlayerTransition : NSObject<UIViewControllerAnimatedTransitioning>
+(instancetype)presentTransitionWithVideoPlayerView:(DYVideoPlayerView *)videoPlayerView;
+(instancetype)dismissTransitionWithVideoPlayerView:(DYVideoPlayerView *)videoPlayerView;
@end

// - DYVideoPlayerView+Private.h

#import "DYVideoPlayerView.h"

@interface DYVideoPlayerView ()

/** 全屏之前的父视图 */
@property (nonatomic, weak) UIView *originalSuperView;

/** 全屏之前的 frame */
@property (nonatomic, assign) CGRect originalFrameInSuperView;

/** 全屏之前的 frame */
@property (nonatomic, assign) CGRect originalFrameInWindow;

@end

// - 实现

#import "DYVideoPlayerVC.h"

#pragma mark - 横屏的控制器
@interface DYVideoPlayerVC ()
/** 播放器 */
@property (nonatomic, assign) UIView *videoPlayerView;

/** 跳转前播放器的父视图 */
@property (nonatomic, assign) UIView *videoPlayerViewOriginalSuperView;

/** 跳转的控制器的方向 */
@property (nonatomic, assign) UIInterfaceOrientation orientation;

@end

@implementation DYVideoPlayerVC
/** 初始化方法 */
- (instancetype)initWithVideoPlayerView:(UIView *)videoPlayerView preferredInterfaceOrientationForPresentation:(UIInterfaceOrientation)orientation
{
    self = [super init];
    if (self) {
        self.modalPresentationStyle = UIModalPresentationFullScreen;
        self.videoPlayerView = videoPlayerView;
        self.transitioningDelegate = self.videoPlayerView;
        self.videoPlayerViewOriginalSuperView = self.videoPlayerView .superview;
        self.orientation = orientation;
    }
    return self;
}

// - MARK: <-- 初始化设置的方法 -->
- (void)viewDidLoad {
    [super viewDidLoad];
}

-(void)viewWillAppear:(BOOL)animated{
    [[UIApplication sharedApplication] setStatusBarHidden:NO];
}

- (BOOL)shouldAutorotate{
    return YES;
}

- (UIInterfaceOrientationMask)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskLandscape;
}

-(UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
    return self.orientation;
}

@end

#pragma mark - 跳转横屏控制器的转场动画
@interface DYVideoPlayerTransition ()

/** 跳转类型 */
@property (nonatomic, assign)DYVideoPlayerTransitionType transitionType;

/** present时候  originalRect->全屏, dismiss时候 : 全屏->originalRect*/
@property (nonatomic, weak) DYVideoPlayerView *videoPlayerView;

@end

@implementation DYVideoPlayerTransition

// - MARK: <-- 生成present和dismiss的转场动画 -->
+(instancetype)presentTransitionWithVideoPlayerView:(DYVideoPlayerView *)videoPlayerView{
    videoPlayerView.originalSuperView = videoPlayerView.superview;
    videoPlayerView.originalFrameInSuperView = videoPlayerView.frame;
    videoPlayerView.originalFrameInWindow = [videoPlayerView.originalSuperView convertRect:videoPlayerView.originalFrameInSuperView toView:[UIApplication sharedApplication].keyWindow];
    DYVideoPlayerTransition *transition = [[DYVideoPlayerTransition alloc] init];
    transition.videoPlayerView = videoPlayerView;
    transition.transitionType = DYVideoPlayerTransitionTypePresent;
    return transition;
}

+(instancetype)dismissTransitionWithVideoPlayerView:(DYVideoPlayerView *)videoPlayerView{
    DYVideoPlayerTransition *transition = [[DYVideoPlayerTransition alloc] init];
    transition.videoPlayerView = videoPlayerView;
    transition.transitionType = DYVideoPlayerTransitionTypeDismiss;
    return transition;
}

// - MARK: <-- 转场动画代理方法 -->
- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext{
    return 3;
}

- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext{
    
    if (_transitionType == DYVideoPlayerTransitionTypePresent) {
        [self presentAnimation:transitionContext];
    }else{
        [self dismissAnimation:transitionContext];
    }
}

/** present 的动画*/
- (void)presentAnimation:(id<UIViewControllerContextTransitioning>)transitionContext{
    // - 跳转的vc
    DYVideoPlayerVC *toVC = (DYVideoPlayerVC *)[transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];

    // - 跳转的vc的view
    UIView *containerView = [transitionContext containerView];
    UIView *toView = toVC.view;
    [containerView addSubview:toView];

    // - 设置原始的位置
    CGRect originalRect;
    CGRect tmpRect = self.videoPlayerView.originalFrameInWindow;
    if (toVC.orientation == UIInterfaceOrientationLandscapeLeft) {
        toView.transform = CGAffineTransformMakeRotation(M_PI / 2);
        originalRect = CGRectMake(
                                  [UIApplication sharedApplication].keyWindow.frame.size.width -  - tmpRect.size.height,
                                  tmpRect.origin.x,
                                  tmpRect.size.height,
                                  tmpRect.size.width);
    }else{
        toView.transform = CGAffineTransformMakeRotation(-M_PI / 2);
        originalRect = CGRectMake(tmpRect.origin.y, tmpRect.origin.x, tmpRect.size.height, tmpRect.size.width);

    }
    
    // - 更换父视图并设置位置
    [toView addSubview:self.videoPlayerView];
    toView.frame = originalRect;
    self.videoPlayerView.frame = toView.bounds;
    [self.videoPlayerView mas_remakeConstraints:^(MASConstraintMaker *make) {
        make.left.right.top.bottom.equalTo(toView);
    }];

    // - 跳转动画
    NSTimeInterval duration = [self transitionDuration:transitionContext];
    [UIView animateWithDuration:duration animations:^{
        toView.transform = CGAffineTransformIdentity;
        toView.frame = [UIApplication sharedApplication].keyWindow.bounds;
        [toView layoutIfNeeded];
    } completion:^(BOOL finished) {
        toView.transform = CGAffineTransformIdentity;
        toView.frame = [UIApplication sharedApplication].keyWindow.bounds;
        [transitionContext completeTransition:YES];
    }];
}

/** dismiss的动画 */
- (void)dismissAnimation:(id<UIViewControllerContextTransitioning>)transitionContext{
    // - 当前的vc
    DYVideoPlayerVC *fromVC = (DYVideoPlayerVC *)[transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    
    // - 当前的view
    UIView *containerView = [transitionContext containerView];
    UIView *fromView = fromVC.view;
    UIView *toView = toVC.view;
    [containerView addSubview:fromView];
    
    toView.frame = [UIApplication sharedApplication].keyWindow.bounds;
    [containerView insertSubview:toView belowSubview:fromView];
    
    // - 返回的动画
    NSTimeInterval duration = [self transitionDuration:transitionContext];
    [UIView animateWithDuration:duration animations:^{
        fromView.transform = CGAffineTransformIdentity;
        fromView.frame = self.videoPlayerView.originalFrameInWindow;
        [fromView layoutIfNeeded];
    } completion:^(BOOL finished) {
        fromView.transform = CGAffineTransformIdentity;
        fromView.frame = self.videoPlayerView.originalFrameInWindow;
        
        // - 更换父视图并设置位置
        [fromVC.videoPlayerViewOriginalSuperView addSubview:fromVC.videoPlayerView];
        fromView.frame = self.videoPlayerView.originalFrameInSuperView;
        [fromVC.videoPlayerView mas_remakeConstraints:^(MASConstraintMaker *make) {
            make.left.mas_equalTo(fromVC.videoPlayerViewOriginalSuperView).offset(self.videoPlayerView.originalFrameInSuperView.origin.x);
            make.top.mas_equalTo(fromVC.videoPlayerViewOriginalSuperView).offset(self.videoPlayerView.originalFrameInSuperView.origin.y);
            make.width.mas_equalTo(self.videoPlayerView.originalFrameInSuperView.size.width);
            make.height.mas_equalTo(self.videoPlayerView.originalFrameInSuperView.size.height);
        }];
        [transitionContext completeTransition:YES];
    }];
}


@end

// - 使用

//
//  DYVideoPlayerView.m
//  QEZB
//
//  Created by 李超群 on 2018/4/23.
//Copyright © 2018年 zhou. All rights reserved.
//

#pragma mark ************************************ 短视频的播放器的 view ************************************

#import "DYVideoPlayerView.h"
#import "DYVideoPlayerVC.h"

@interface DYVideoPlayerView () <UIViewControllerTransitioningDelegate>

/** <#注释#> */
@property (nonatomic, weak) UIViewController *videoPlayerVC;

@end

@implementation DYVideoPlayerView

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    [self toRightScreenModel];
}

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(statusBarOrientationChange:) name:UIDeviceOrientationDidChangeNotification object:nil];

    }
    return self;
}

- (void)statusBarOrientationChange:(NSNotification *)notification {
    UIDeviceOrientation orientation = [UIDevice currentDevice].orientation;
    if (orientation == UIDeviceOrientationLandscapeLeft ) {
        [self toLeftScreenModel];
    }else if (orientation == UIDeviceOrientationLandscapeRight) {
        [self toRightScreenModel];
    }else if (orientation == UIDeviceOrientationPortrait) {
        [self toSmallScreenModel];
    }
}

-(void)toSmallScreenModel{
    self.videoPlayerVC.transitioningDelegate = self;
    [self.videoPlayerVC dismissViewControllerAnimated:YES completion:nil];
    self.videoPlayerVC = nil;
}


-(void)toLeftScreenModel{
    // - 如果已经在全屏模式, 不操作
    if (self.videoPlayerVC) return;

    // - 旋转到大屏回调
    if ([self.delegate respondsToSelector:@selector(playerView:willRotateToFullScreen:)]) {
        [self.delegate playerView:self willRotateToFullScreen:YES];
    }

    // - 跳转到大屏
    DYVideoPlayerVC *videoPlayerVC = [[DYVideoPlayerVC alloc]initWithVideoPlayerView:self preferredInterfaceOrientationForPresentation:UIInterfaceOrientationLandscapeRight];
    UIImageView *tempV = [[UIImageView alloc]initWithImage:[UIImage imageCaptureTheFullScreen]];
    [[UIApplication sharedApplication].keyWindow.rootViewController.view addSubview:tempV];
    [[ControllerTool getCurrentVC] presentViewController:videoPlayerVC animated:YES completion:^{
        [tempV removeFromSuperview];
    }];
    self.videoPlayerVC = videoPlayerVC;
}
/** 旋转到大屏模式(右边) */
-(void)toRightScreenModel{
    // - 如果已经在全屏模式, 不操作
    if (self.videoPlayerVC) return;

    // - 旋转到大屏回调
    if ([self.delegate respondsToSelector:@selector(playerView:willRotateToFullScreen:)]) {
        [self.delegate playerView:self willRotateToFullScreen:YES];
    }

    // - 跳转到大屏
    DYVideoPlayerVC *videoPlayerVC = [[DYVideoPlayerVC alloc]initWithVideoPlayerView:self preferredInterfaceOrientationForPresentation:UIInterfaceOrientationLandscapeLeft];
    UIImageView *tempV = [[UIImageView alloc]initWithImage:[UIImage imageCaptureTheFullScreen]];
    [[UIApplication sharedApplication].keyWindow.rootViewController.view addSubview:tempV];
    [[ControllerTool getCurrentVC] presentViewController:videoPlayerVC animated:YES completion:^{
        [tempV removeFromSuperview];
    }];
    self.videoPlayerVC = videoPlayerVC;
}

- (id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source{
    return [DYVideoPlayerTransition presentTransitionWithVideoPlayerView:self];
}

- (nullable id <UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed{
    return [DYVideoPlayerTransition dismissTransitionWithVideoPlayerView:self];
}

@end

本文地址:https://blog.csdn.net/qq_27074387/article/details/107133650