需求:视频小窗全屏切换
效果1:状态栏不转屏 (大多数App使用)
效果2:状态栏转屏
实现:
一、状态栏不转屏
试想一下:视频小窗下面有简介、评论列表、剧集推荐……整个界面转屏??别闹了
看上面效果图就能想到一个思路:通过检测设备方向,改变视频父视图(videoView)的大小和方向。
实现:
1.检测设备方向
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:[UIDevice currentDevice]];
2.实现通知方法
- (void)orientationChanged:(NSNotification *)notify{
UIDevice *device = notify.object;
switch (device.orientation) {
case UIDeviceOrientationLandscapeLeft:
{
AXLog(@"屏幕向左平躺");
if (self.player.isFullScreen) {
// 如果已全屏,不做任何处理
}else{
self.player.isFullScreen = YES;
}
}
break;
case UIDeviceOrientationPortrait:
{
AXLog(@"屏幕直立");
if (self.player.isFullScreen) {
self.player.isFullScreen = NO;
}else{ // 如果已小窗,不做任何处理
}
}
break;
default:
NSLog(@"无法辨认");
break;
}
}
3.再来看看 self.player.isFullScreen = NO/YES;起到什么作用呢?
- (void)setIsFullScreen:(BOOL)isFullScreen{
_isFullScreen = isFullScreen;
// 更改全屏按钮状态
self.bottomBar.changeScreenBtn.selected = isFullScreen;
// 根据是否全屏更改底部工具条的布局
self.bottomBar.isFullScreenUpdate = isFullScreen;
// 开始转屏
if (self.isFullScreen) {
[self beginEnterFullScreen];
}else{
[self beginOutFullScreen];
}
// 告诉使用此videoPlayer的控制器,进而做一些额外的操作,可忽略
if ([self.delegate respondsToSelector:@selector(videoPlayer:didChangePlayerFullScreenState:)]) {
[self.delegate videoPlayer:self didChangePlayerFullScreenState:self.isFullScreen];
}
}
#pragma mark - 转屏处理逻辑
- (void)beginEnterFullScreen{
[UIView animateWithDuration:0.2 animations:^{
self.playerView.frame = CGRectMake(0, 0, kScreenHeight, kScreenWidth);
self.playerView.center = CGPointMake(kScreenWidth/2, kScreenHeight/2);
CGAffineTransform rotate = CGAffineTransformMakeRotation(M_PI/2);
self.playerView.transform = rotate;
} completion:^(BOOL finished) {
}];
}
- (void)beginOutFullScreen{
[UIView animateWithDuration:0.2 animations:^{
self.playerView.transform = CGAffineTransformIdentity;
self.playerView.frame = CGRectMake(0, 0, kScreenWidth, kVideoViewHeight);
} completion:^(BOOL finished) {
}];
}
// 其实就是一个 view 的 frame + transform 的 animation 🤣 超easy
4.当你destroy播放器的时候,别忘了
[[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
[NSNotificationCenter removeAllObserverForObj:self];
二、状态栏转屏
NSInvocation 不了解的话,可以补充下Rutime知识。
- (void)viewWillLayoutSubviews
{
[self shouldRotateToOrientation:(UIDeviceOrientation)[UIApplication sharedApplication].statusBarOrientation];
}
- (void)changeScreenAction
{
if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)])
{
NSNumber *num = [[NSNumber alloc] initWithInt:(_isFullScreen?UIInterfaceOrientationLandscapeRight:UIInterfaceOrientationPortrait)];
[[UIDevice currentDevice] performSelector:@selector(setOrientation:) withObject:(id)num];
[UIViewController attemptRotationToDeviceOrientation];
}
SEL selector=NSSelectorFromString(@"setOrientation:");
NSInvocation *invocation =[NSInvocation invocationWithMethodSignature:[UIDevice instanceMethodSignatureForSelector:selector]];
[invocation setSelector:selector];
[invocation setTarget:[UIDevice currentDevice]];
int val = _isFullScreen?UIInterfaceOrientationLandscapeRight:UIInterfaceOrientationPortrait;
[invocation setArgument:&val atIndex:2];
[invocation invoke];
}
#pragma mark - 转屏处理逻辑
-(void)shouldRotateToOrientation:(UIDeviceOrientation)orientation {
if (orientation == UIDeviceOrientationPortrait ||orientation == UIDeviceOrientationPortraitUpsideDown) {
// 竖屏
_isFullScreen = NO;
_playerView.frame = PlayerHalfFrame;
}
else {
// 横屏
CGFloat width = [UIScreen mainScreen].bounds.size.width;
CGFloat height = [UIScreen mainScreen].bounds.size.height;
if (width < height)
{
CGFloat tmp = width;
width = height;
height = tmp;
}
_isFullScreen = YES;
_playerView.frame = CGRectMake(0, 0, width, height);
}
}