zoukankan      html  css  js  c++  java
  • iOS 视频全屏功能 学习

    项目中,也写过类似"视频全屏"的功能, 前一阵子读到今日头条 的一篇技术文章,详细介绍三种旋转方法差异优劣最终择取。文章从技术角度看写的非常好,从用户角度看,也用过多家有视频功能的app,今日头条的体验的确很优。特别值得学习特此参考写了一个视频全屏小功能

     实现方法:配合重写当前的ViewController的shouldAutorotate方法,返回NO 并且控制 状态栏的展示  然后 通过 animation旋转动画处理UI相对布局 

    (1)组织类别方法 UINavigationController+Rotation 目的视频旋转 状态栏也要旋转

    //
    //  UINavigationController+Rotation.h
    //  SectionDemo
    //
    //  Created by HF on 17/4/1.
    //  Copyright © 2017年 HF-Liqun. All rights reserved.
    //
    
    #import <UIKit/UIKit.h>
    
    @interface UINavigationController (Rotation)
    
    @end
    //
    //  UINavigationController+Rotation.m
    //  SectionDemo
    //
    //  Created by HF on 17/4/1.
    //  Copyright © 2017年 HF-Liqun. All rights reserved.
    //
    
    #import "UINavigationController+Rotation.h"
    
    @implementation UINavigationController (Rotation)
    
    - (BOOL)shouldAutorotate
    {
        return [[self.viewControllers lastObject] shouldAutorotate];
    }
    
    
    - (NSUInteger)supportedInterfaceOrientations
    {
        return [[self.viewControllers lastObject] supportedInterfaceOrientations];
    }
    
    
    - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
        return [[self.viewControllers lastObject] preferredInterfaceOrientationForPresentation];
    }
    
    @end

    (2)视频UI HFMovieView

    //
    //  HFMovieView.h
    //  SectionDemo
    //
    //  Created by HF on 17/4/1.
    //  Copyright © 2017年 HF-Liqun. All rights reserved.
    //
    
    #import <UIKit/UIKit.h>
    #import "HFPlayerView.h"
    
    typedef NS_ENUM(NSUInteger, MovieViewState) {
        MovieViewStateSmall,
        MovieViewStateAnimating,
        MovieViewStateFullscreen,
    };
    
    @interface HFMovieView : UIView
    
    /**
     视频播放对象
     */
    @property (nonatomic, strong)HFPlayerView *videoView;
    
    /**
     记录小屏时的parentView
     */
    @property (nonatomic, weak) UIView *movieViewParentView;
    
    /**
     记录小屏时的frame
     */
    @property (nonatomic, assign) CGRect movieViewFrame;
    
    @property (nonatomic, assign) MovieViewState state;
    
    
    @end
    //
    //  HFMovieView.m
    //  SectionDemo
    //
    //  Created by HF on 17/4/1.
    //  Copyright © 2017年 HF-Liqun. All rights reserved.
    //
    
    #import "HFMovieView.h"
    
    @implementation HFMovieView
    
    - (instancetype)initWithFrame:(CGRect)frame
    {
        self = [super initWithFrame:frame];
        if (self) {
            
             //videoView
            [self addSubview:self.videoView];
            
            //others
            UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)];
            [self.videoView addGestureRecognizer:tapGestureRecognizer];
        
        }
        return self;
    }
    
    #pragma mark - event
    
    - (void)handleTapGesture:(UITapGestureRecognizer *)sender
    {
        if (sender.state == UIGestureRecognizerStateEnded)
        {
            if (self.state == MovieViewStateSmall) {
                [self enterFullscreen];
            }
            else if (self.state == MovieViewStateFullscreen) {
                [self exitFullscreen];
            }
        }
    }
    
    #pragma mark - private
    
    #pragma mark -- 全屏 animation
    - (void)enterFullscreen {
        
        if (self.state != MovieViewStateSmall) {
            return;
        }
        
        self.state = MovieViewStateAnimating;
        
        /*
         * 记录进入全屏前的parentView和frame
         */
        self.movieViewParentView = self.videoView.superview;
        self.movieViewFrame = self.videoView.frame;
        
        /*
         * movieView移到window上
         */
        CGRect rectInWindow = [self convertRect:self.videoView.bounds toView:[UIApplication sharedApplication].keyWindow];
        [self.videoView removeFromSuperview];
        self.videoView.frame = rectInWindow;
        [[UIApplication sharedApplication].keyWindow addSubview:self.videoView];
        
        /*
         * 执行动画
         */
        [UIView animateWithDuration:0.5 animations:^{
            self.videoView.transform = CGAffineTransformMakeRotation(M_PI_2);
            self.videoView.bounds = CGRectMake(0, 0, CGRectGetHeight(self.videoView.superview.bounds), CGRectGetWidth(self.videoView.superview.bounds));
            self.videoView.center = CGPointMake(CGRectGetMidX(self.videoView.superview.bounds), CGRectGetMidY(self.videoView.superview.bounds));
        } completion:^(BOOL finished) {
            self.state = MovieViewStateFullscreen;
        }];
        
        [self refreshStatusBarOrientation:UIInterfaceOrientationLandscapeRight];
    }
    
    #pragma mark -- 退出全屏 animation
    
    - (void)exitFullscreen
    {
        if (self.state != MovieViewStateFullscreen) {
            return;
        }
        
        self.state = MovieViewStateAnimating;
        
        CGRect frame = [self.movieViewParentView convertRect:self.movieViewFrame toView:[UIApplication sharedApplication].keyWindow];
        
        [UIView animateWithDuration:0.5 animations:^{
            self.videoView.transform = CGAffineTransformIdentity;
            self.videoView.frame = frame;
        } completion:^(BOOL finished) {
            /*
             * movieView回到小屏位置
             */
            [self.videoView removeFromSuperview];
            self.videoView.frame = self.movieViewFrame;
            [self.movieViewParentView addSubview:self.videoView];
            self.state = MovieViewStateSmall;
        }];
        
        [self refreshStatusBarOrientation:UIInterfaceOrientationPortrait];
    }
    
    
    #pragma mark -- 更新状态栏方向
    
    - (void)refreshStatusBarOrientation:(UIInterfaceOrientation)interfaceOrientation {
        [[UIApplication sharedApplication] setStatusBarOrientation:interfaceOrientation animated:YES];
    }
    
    
    #pragma mark - setter and getter
    
    - (HFPlayerView *)videoView
    {
        if (!_videoView) {
            _videoView = [[HFPlayerView alloc]initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
            _videoView.backgroundColor = [UIColor blackColor];
        }
        return _videoView;
    }
    
    
    @end

    (3)视图控制器

    //
    //  MethodDetailViewController.h
    //  SectionDemo
    //
    //  Created by HF on 17/4/1.
    //  Copyright © 2017年 HF-Liqun. All rights reserved.
    //
    
    #import <UIKit/UIKit.h>
    #import "HFMovieView.h"
    
    @interface MethodDetailViewController : UIViewController
    
    @property (nonatomic, strong) HFMovieView *moviewView;
    
    @end
    //
    //  MethodDetailViewController.m
    //  SectionDemo
    //
    //  Created by HF on 17/4/1.
    //  Copyright © 2017年 HF-Liqun. All rights reserved.
    //
    
    #import "MethodDetailViewController.h"
    
    @interface MethodDetailViewController ()
    
    @property (nonatomic, strong) UITableView *tableView;
    @property (nonatomic, strong) UIView *headView;
    
    @end
    
    @implementation MethodDetailViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        [self.view addSubview:self.tableView];
        [self.tableView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.edges.equalTo(self.view);
        }];
        
        self.tableView.tableHeaderView = self.headView;
        [self.headView addSubview:self.moviewView];
    
    }
    
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    
    #pragma mark - 旋转配置
    
    - (BOOL)shouldAutorotate {
        return NO;
    }
    
    #pragma mark - setter/getter
    
    - (UITableView *)tableView
    {
        if (!_tableView) {
            _tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
            _tableView.backgroundColor = [UIColor clearColor];
            // _tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
            
        }
        return  _tableView;
    }
    
    - (UIView *)headView
    {
        if (!_headView) {
            _headView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 200)];;
            _headView.backgroundColor = [UIColor lightGrayColor];
        }
        return _headView;
    }
    
    - (HFMovieView *)moviewView
    {
        if (!_moviewView) {
            _moviewView = [[HFMovieView alloc]initWithFrame:CGRectMake(0, 0,  self.view.frame.size.width, 200)];
            _moviewView.backgroundColor = [UIColor yellowColor];
        }
        return _moviewView;
    }
    @end

    效果图:

     (4)参考之前 写过视频播放的相关方法 优化架构分工 

      参考 SectionDemo 

    参考:

    1. https://techblog.toutiao.com/2017/03/28/fullscreen/

    2. iOS AVPlayer 学习

  • 相关阅读:
    linux LVM详解
    Mysql SQL优化系列之——执行计划连接方式浅释
    Vue SSR常见问题、异常处理以及优化方案
    vue组件生命周期详解
    axios全局设置url公共请求头
    WebView中JS调用Android Method 遇到的坑整理
    node.js项目多环境配置
    用vue构建多页面应用
    前端系列-移动端开发踩过的一些坑
    Async:简洁优雅的异步之道
  • 原文地址:https://www.cnblogs.com/someonelikeyou/p/6890256.html
Copyright © 2011-2022 走看看