横屏竖屏转换

news/2024/11/15 16:42:13/

在App Store上的大部分视频播放App中,都实现了竖屏小屏播放以显示更多相关信息,横屏切换到全屏播放,这样的交互显得优雅而大方。最近项目里有个这样的需求,为全屏视频播放加上竖屏模式。下面,让我们一起来实现这个需求。


iOS中的方向

iOS设备中有两种方向,一种是设备方向,一种是屏幕视图方向。我们可以直接调用

[objc]  view plain copy
  1. [UIDevice currentDevice] setOrientation:UIInterfaceOrientationPartrait];  

强制更改设备方向,但该方法已经在iOS6中废止。另外一种更改设备方向的方法是通过重力感应触发。

那么视图方向是又什么决定的呢?

  1. 全局Info.plist
  2. iOS6+在UIApplicationDelegate中增加了 - (NSUInteger)supportedInterfaceOrientationsForWindow:(UIWindow *)window;回调
  3. UIViewController。并且只在UIWindow的rootViewController或model状态下的UIViewController有效

最终的视图方向取决于 (全局控制 ∩ UIWindow 中的回调 ∩ 单个界面控制) 的交集,如果交集为空,iOS6下抛出 UIApplicationInvalidInterfaceOrientationException 异常后崩溃。

UIController中对视图方向变化的响应

iOS5:

[objc]  view plain copy
  1. -(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation  
  2. {  
  3.     return ((toInterfaceOrientation == UIInterfaceOrientationLandscapeRight) |  
  4.            (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft));  
  5. }  
iOS6+:

[objc]  view plain copy
  1. // 支持转屏?  
  2. (BOOL)shouldAutorotate  
  3. {  
  4.     return YES;  
  5. }  
  6. // 支持的屏幕方向  
  7. - (NSUInteger)supportedInterfaceOrientations  
  8. {  
  9.     return UIInterfaceOrientationMaskLandscape;  
  10. }  

实现前后的效果

竖屏:


横屏:


两张横竖屏的图片中,菜单、标题大小都发生了改变。下面我们就来讨论下实现的方法。

实现细节

  1. 首先在视频播放所在UIViewController支持横竖屏,并在设备旋转的回调中,通知菜单当前的设备方向发生了改变,代码如下:
    [objc]  view plain copy
    1. //设备旋转前  
    2. - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration  
    3. {  
    4. //横竖屏变更菜单等  
    5. if (toInterfaceOrientation == UIInterfaceOrientationPortrait) {  
    6. //竖屏状态  
    7. }  
    8.    
    9. //设备旋转前  
    10. - (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration  
    11. {  
    12. //对视图进行旋转处理,这里通过present一个新的UIViewController,暂不需要处理  
    13. }  
    14.    
    15. //设备旋转完  
    16. - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation  
    17. {  
    18. //设备旋转完的处理  
    19. }  
    20. // 支持转屏  
    21. (BOOL)shouldAutorotate  
    22. {  
    23.     return YES;  
    24. }  
    25. // 支持的屏幕方向  
    26. - (NSUInteger)supportedInterfaceOrientations  
    27. {  
    28.     return UIDeviceOrientationLandscapeLeft | UIInterfaceOrientationPortrait ;  
    29. }  
    30. -(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation  
    31. {  
    32.     return ((toInterfaceOrientation == UIInterfaceOrientationPortrait) ||  
    33.            (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft));  
    34. }  
    willRotateToInterfaceOrientation:duration: 和 willAnimateRotationToInterfaceOrientation:duration:的区别在于调用的顺序。前者在旋转前调用,并且屏幕方向、设备原点、视图大小等都未改变,后者在旋转的动画block中调用,并且屏幕方向、设备原点、视图大小等都已改变。因此在willRotateToInterfaceOrientation:duration:中,应当做变量的更改;在willAnimateRotationToInterfaceOrientation:duration:中,适合做一些重绘工作。
  2. 考虑到原来的视频播放器只支持横屏播放,这里采用的方案如下:竖屏状态下,先present一个只支持横屏的UIViewController,再将视频播放器作为横屏UIViewController的子控制器添加进来。这样可以触发iOS进行横竖屏检测。
  3. 当竖屏切到横屏时,旋转的动画设置。代码如下:
    [objc]  view plain copy
    1. [portraitViewController presentViewController:landscapeViewController animated:NO completion:^{  
    2.   
    3.             //mvPlayer原先是作为protraitViewController的子UIViewController  
    4.             [mvPlayer.view removeFromSuperview];   
    5.             [mvPlayer removeFromParentViewController];  
    6.   
    7.             //改为作为landscapeViewController的子UIViewController  
    8.         [landscapeViewController addChildViewController:mvPlayer];  
    9.             [landscapeViewController.view addSubview:mvPlayer.view];   
    10.               
    11.             //改变状态栏方向  
    12.             [[UIApplication sharedApplication] setStatusBarHidden:YES];  
    13.             [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeLeft animated:NO];  
    14.               
    15.             //旋转前  
    16.             CGAffineTransform transform = CGAffineTransformMakeRotation(-M_PI_2);  
    17.             transform = CGAffineTransformScale(transform, scale, scale);  
    18.             mvPlayer.view.transform = transform;  
    19.               
    20.             //旋转动画  
    21.             [UIView animateWithDuration:[[UIApplication sharedApplication] statusBarOrientationAnimationDuration] animations:^{  
    22.                 mvPlayer.view.transform = CGAffineTransformIdentity;  
    23.                 mvPlayer.view.frame = landscapeViewController.view.bounds;  
    24.             }completion:^(BOOL finished) {  
    25.                   
    26.                 [[UIApplication sharedApplication] setStatusBarHidden:NO];  
    27.                   
    28.             }];  
    29.         }];  

  4. 横屏切换到竖屏的动画实现如下:
    [objc]  view plain copy
    1. //更改mvPlayer的父UIController  
    2. [mvPlayer.view removeFromSuperview];  
    3. UIViewController *viewController = strongSelf.player.presentingViewController;  
    4. [mvPlayer removeFromParentViewController];  
    5. [viewController dismissModalViewControllerAnimated:NO];  
    6.   
    7. [portraitViewController addChildViewController:mvPlayer];  
    8. [portraitViewController.view addSubview:mvPlayer.view];  
    9.           
    10. //缩放动画  
    11. CGAffineTransform transform = CGAffineTransformMakeScale(scale, scale);  
    12. mvPlayer.view.transform = transform;  
    13. mvPlayer.view.frame = CGRectMake(00, CGRectGetWidth(mvPlayer.view.frame), CGRectGetHeight(mvPlayer.view.frame));  
    14. mvPlayer.view.transform = CGAffineTransformRotate(transform, M_PI_2);  
    15.           
    16.      [UIView animateWithDuration:[[UIApplication sharedApplication] statusBarOrientationAnimationDuration]  
    17.                       animations:^{  
    18.                           mvPlayer.view.transform = CGAffineTransformMakeScale(scale, scale);  
    19.                       }  
    20.                       completion:^(BOOL finished) {  
    21.                           mvPlayer.view.frame = CGRectMake(00, CGRectGetWidth(mvPlayer.view.frame), CGRectGetHeight(mvPlayer.view.frame));  
    22.                                 
    23.                       }];  

  5. 以上是手动旋转过程。还有一种方法是直接旋转portraitViewController.view。人为旋转过程中,设备的原点并未发生改变,这需要考虑横竖屏布局问题。

总结

本文介绍横竖屏切换的一些基础知识,并实践了类似腾讯视频的横竖屏人为切换方式,达到不同状态下显示不同视图的交互方式。


http://www.ppmy.cn/news/696657.html

相关文章

横屏竖屏切换

当用N85、N95的时候,可以横屏竖屏切换。当切换的时候,就要把程序中的控件位置、大小重新计算,重新画了。 其实也没有什么困难的。 1.这根据原始屏幕(240*320)的屏幕计算坐标。当横屏竖屏切换的时候,可以用下面的公式进行自动的拉…

Win7屏幕显示方向怎么调整为竖屏显示操作教学分享

Win7屏幕显示方向怎么调整为竖屏显示操作教学分享。有的用户在进行电脑投屏内容展示的时候,需要进行竖屏的内容展示。那么怎么将系统的所有内容调整成为竖屏来进行展示呢?接下来一起来看看以下操作方法分享吧。 操作步骤 1、首先点击屏幕左下角的“开始”…

设置屏幕默认横屏

设置屏幕默认横屏应该在AndroidManifest.xml中的android:screenOrientation属性中设置 android:screenOrientation"landscape" 而不是通过代码设置(以前喜欢在BaseActivity中通过代码设置) if (getRequestedOrientation() ! ActivityInfo.SCREEN_ORIENTATION_LANDSCA…

为什么电脑屏幕会横过来_电脑屏幕横过来了怎么办

电脑屏幕是人与电脑交互的窗口,所有可视化的操作都是通过电脑屏幕来呈现。可是有些小伙伴却遇到了一些问题,电脑屏幕不知道什么时候横过来了,人与电脑的交互窗口就莫名复杂了。该如何调整过来呢?往下瞧 在使用电脑的时候&#xff…

如何解决电脑横屏问题

今天一不小心碰到键盘,使得电脑屏幕旋转了,想用自己的电脑查查怎么解决,操作起来真费劲,赶紧向少然求救。 解决方案: 在桌面上,点击鼠标右键,选择图形选项→旋转→内置显示器→旋转至0度&#x…

计算机硬盘排列怎么变回横的,电脑屏幕横向了怎么调回来

大家好,我是时间财富网智能客服时间君,上述问题将由我为大家进行解答。 电脑屏幕横向了调回来的方法如下: 1、首先右键点击桌面空白处,在弹出的菜单中选择屏幕分辨率。 2、点击方向旁边的向下箭头,将原来的纵向改为横向…

SpringBoot3中的属性绑定注解和YMAL配置文件、日志

1. 常用注解 SpringBoot摒弃XML配置方式,改为全注解驱动 1. 组件注册 Configuration、SpringBootConfiguration Bean、Scope Controller、Service、Repository、Component Import ComponentScan 步骤: 1、Configuration 编写一个配置类 2、在配置类中…

FDM3D打印系列——5、上色和灯光

3D打印扎古头可动并加灯 大家好,我是阿赵,这次通过一个实际操作的例子,来聊一下3D打印模型添加效果。这里主要讲2个方面,一个是上色,另一个是加灯光 一、上色 这个扎古头模型就是这次的主角。 1、打磨 可以看到&…