iOS 视频全屏功能 学习

时间:2023-03-09 04:04:39
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

效果图:

iOS  视频全屏功能 学习

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

参考 SectionDemo

参考:

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

2. iOS AVPlayer 学习