需求:視頻小窗全屏切換
效果1:狀態欄不轉屏 (大多數App使用)
效果2:狀態欄轉屏
實現:
一、狀態欄不轉屏
videoDemo1.gif
試想一下:視頻小窗下面有簡介、評論列表、劇集推薦……整個界面轉屏??別鬧了
看上面效果圖就能想到一個思路:通過檢測設備方向,改變視頻父視圖(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);
}
}