我的应用仅适用于iphone
设备(iphone 4和5),并且仅支持ios 6
。
我的整个应用只支持portrait
模式。但是有一个名为“ChatView
”的视图,我希望同时支持landscape
和portrait
模式。
我已按如下方式设置所需的设备旋转 -
我还尝试使用以下代码来支持“ChatView”中的旋转 -
-(BOOL)shouldAutorotate
{
return YES;
}
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscape;
}
但它无法旋转那个视图。
我已经搜索了很多,但无法找到我的问题的解决方案。
并且在“ChatView”中还有一些对象,如按钮,文本字段,其帧设置为programmaticaly。所以我想知道我是否还必须为横向模式设置所有这些对象的帧?
请帮帮我。
感谢.....
答案 0 :(得分:62)
简单但工作得很好。 IOS 7.1和8
AppDelegate.h
@property () BOOL restrictRotation;
AppDelegate.m
-(NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
if(self.restrictRotation)
return UIInterfaceOrientationMaskPortrait;
else
return UIInterfaceOrientationMaskAll;
}
的ViewController
-(void) restrictRotation:(BOOL) restriction
{
AppDelegate* appDelegate = (AppDelegate*)[UIApplication sharedApplication].delegate;
appDelegate.restrictRotation = restriction;
}
viewDidLoad中
[self restrictRotation:YES]; or NO
答案 1 :(得分:28)
我认为如果你只想支持一个viewcontroller轮换,那么因为应用程序将遵循你在.plist
文件中设置的方向,所以不可能。您可以遵循的替代方案是支持横向和纵向的应用程序,将所有视图控制器旋转冻结为纵向,聊天视图除外。
修改强>
要创建一个名为UINavigationController
的新文件,请创建一个名称为CustomNavigationController
并将其设为UINavigationController
的子类。
.h文件
#import <UIKit/UIKit.h>
@interface CustomNavigationController : UINavigationController
@end
.m文件
#import "CustomNavigationController.h"
@interface CustomNavigationController ()
@end
@implementation CustomNavigationController
-(BOOL)shouldAutorotate
{
return NO;
}
-(UIInterfaceOrientationMask)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskAll;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return UIInterfaceOrientationIsPortrait(interfaceOrientation);
}
@end
将主类xib中UINavigationController
的班级设为CustomNavigationController
。希望它有助于ypu ..
答案 2 :(得分:21)
您的视图控制器永远不会旋转到应用程序本身不支持的任何位置。您应该启用所有可能的旋转,然后在不应旋转的视图控制器中添加以下行
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
在ChatView中,它应该是:
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskAll;
}
如果您需要在轮换后更改布局,则应在
中对子视图实施适当的更改- (void)viewWillLayoutSubviews
使用self.view.bounds
检查view
的当前大小,因为self.view.frame
在轮换后不会改变。
答案 3 :(得分:15)
表示您要旋转的特定viewcontroller.m
添加此方法:
- (BOOL)canAutoRotate
{
return YES;
}
然后在AppDelegate.m
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
UIViewController *currentViewController = [self topViewController];
if ([currentViewController respondsToSelector:@selector(canAutoRotate)]) {
NSMethodSignature *signature = [currentViewController methodSignatureForSelector:@selector(canAutoRotate)];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
[invocation setSelector:@selector(canAutoRotate)];
[invocation setTarget:currentViewController];
[invocation invoke];
BOOL canAutorotate = NO;
[invocation getReturnValue:&canAutorotate];
if (canAutorotate) {
return UIInterfaceOrientationMaskAll;
}
}
return UIInterfaceOrientationMaskPortrait;
}
- (UIViewController *)topViewController
{
return [self topViewControllerWithRootViewController:[UIApplication sharedApplication].keyWindow.rootViewController];
}
- (UIViewController *)topViewControllerWithRootViewController:(UIViewController *)rootViewController
{
if ([rootViewController isKindOfClass:[UITabBarController class]]) {
UITabBarController* tabBarController = (UITabBarController*)rootViewController;
return [self topViewControllerWithRootViewController:tabBarController.selectedViewController];
} else if ([rootViewController isKindOfClass:[UINavigationController class]]) {
UINavigationController* navigationController = (UINavigationController*)rootViewController;
return [self topViewControllerWithRootViewController:navigationController.visibleViewController];
} else if (rootViewController.presentedViewController) {
UIViewController* presentedViewController = rootViewController.presentedViewController;
return [self topViewControllerWithRootViewController:presentedViewController];
} else {
return rootViewController;
}
}
答案 4 :(得分:3)
特德的回答与挪威亚历山大提到的问题很吻合。 但我认为这个问题并没有像亚历山大解释的那样发生,
当ViewController B当前处于横向状态时(全部 已启用方向)返回ViewController A.(肖像 只有)用户点击后退按钮后, supportedInterfaceOrientationsForWindow不会被调用 ViewController A以横向
结束
实际上,当用户点击后退按钮后,当前处于横向(启用了所有方向)的ViewController B返回ViewController A(仅限肖像)时,Appdelegate
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation;
正在被召唤。但仍然根视图控制器是ViewController B(启用旋转的视图控制器),ViewController A没有回到纵向,因为ViewController B仍在返回
-(BOOL)shouldAutorotate{
return YES;
}
因此当您按下返回按钮返回时,ViewController B中的“shouldAutorotate - &gt; NO”。然后ViewController A将进入纵向方向。这就是我所做的
@property (nonatomic, assign) BOOL canAutoRotate;
#pragma mark - Public methods
- (BOOL)canAutoRotate
{
return _canAutoRotate;
}
#pragma mark - Button actions
- (void)backButtonPressed:(UIButton *)sender {
_canAutoRotate = NO;
(...)
}
#pragma mark - Init
- (id)init{
if(self=[super init]) {
_canAutoRotate = YES;
}
return self;
}
答案 5 :(得分:1)
根据@ iAnum的回答,我已经启用了自动旋转和UIViewController类检测。
这是因为否则转入和转出特殊视图控制器&#34;不会对纵向方向进行纠正,而且你会被困在一个不受支持的方向。
我只有一个视图支持横向,所以我只是在自定义导航视图控制器中对其进行了硬编码:
-(BOOL)shouldAutorotate
{
return YES;
}
-(NSUInteger)supportedInterfaceOrientations
{
//Access the current top object.
UIViewController *viewController = [self.viewControllers lastObject];
//Is it one of the landscape supported ones?
if ([viewController isMemberOfClass:[SpecialViewController class]]) {
return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight;
} else
return UIInterfaceOrientationMaskPortrait;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
//Access the current top object.
UIViewController *viewController = [self.viewControllers lastObject];
//Is it one of the landscape supported ones?
if ([viewController isMemberOfClass:[SpecialViewController class]]) {
return interfaceOrientation;
} else
return UIInterfaceOrientationIsPortrait(interfaceOrientation);
}
在这里讨论的问题突然出现的风险投资https://stackoverflow.com/a/15057537/1277350在景观中回击甚至没有调用定位方法,所以你必须通过显示和驳回模态观点。
然后记住,如果你想要触发willShowViewController,你需要设置self.delegate = self并将UINavigationControllerDelegate和下面的代码一起添加到自定义导航控制器。
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationPortrait;
}
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
UIApplication* application = [UIApplication sharedApplication];
if (application.statusBarOrientation != UIInterfaceOrientationPortrait)
{
UIViewController *c = [[UIViewController alloc]init];
[c.view setBackgroundColor:[UIColor clearColor]];
[navigationController presentViewController:c animated:NO completion:^{
[self dismissViewControllerAnimated:YES completion:^{
}];
}];
}
}
答案 6 :(得分:1)
创建UINavigationController的子类,如下所示:
MyNavigationController.h
#import <UIKit/UIKit.h>
@interface MyNavigationController : UINavigationController
@end
MyNavigationController.m
#import "MyNavigationController.h"
#import "ServicesVC.h"
@implementation MyNavigationController
-(BOOL)shouldAutorotate{
return YES;
}
-(NSUInteger)supportedInterfaceOrientations{
if ([[self.viewControllers lastObject] isKindOfClass:[ServicesVC class]]) {
return UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight;
}
return UIInterfaceOrientationMaskAll;
}
@end
假设您的viewcontroller被命名为:ServicesVC
答案 7 :(得分:1)
以下是亚历山大(https://stackoverflow.com/posts/25507963/revisions)在斯威夫特中的答案:
func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> Int {
var currentViewController: UIViewController? = self.topViewController()
if currentViewController != nil && currentViewController!.canAutoRotate() {
return Int(UIInterfaceOrientationMask.All.rawValue)
}
return Int(UIInterfaceOrientationMask.Portrait.rawValue)
}
func topViewController() -> UIViewController? {
if UIApplication.sharedApplication().keyWindow != nil
{
return self.topViewControllerWithRootViewController(UIApplication.sharedApplication().keyWindow!.rootViewController!)
}
return nil
}
func topViewControllerWithRootViewController(rootViewController: UIViewController?) -> UIViewController? {
if rootViewController == nil {
return nil
}
if rootViewController!.isKindOfClass(UITabBarController) {
var tabBarController: UITabBarController = (rootViewController as? UITabBarController)!
return self.topViewControllerWithRootViewController(tabBarController.selectedViewController)
}
else {
if rootViewController!.isKindOfClass(UINavigationController) {
var navigationController: UINavigationController = (rootViewController as? UINavigationController)!
return self.topViewControllerWithRootViewController(navigationController.visibleViewController)
}
else {
if (rootViewController!.presentedViewController != nil) {
var presentedViewController: UIViewController = rootViewController!.presentedViewController!
return self.topViewControllerWithRootViewController(presentedViewController)
}
else {
return rootViewController
}
}
}
}
此外,您还需要在AppDelegate.swift中添加以下代码段:
extension UIViewController {
func canAutoRotate() -> Bool {
return false
}}
对于要允许所有旋转的ViewControllers,添加此功能:
override func canAutoRotate() -> Bool {
return true
}
答案 8 :(得分:1)
我不确定此问题的历史(现在= iOS 10时间范围),但在2016年10月发布此时,最简单的解决方案丢失了。
假设你想要这个:
UINavigationController
,而无需对其进行任何操作...然后(IMO)最简单的解决方案是制作UINavigationControllerDelegate ,而不是子类UINavigationController(违反上面的假设4)。
当我解决这个问题时,我决定我的第一个ViewController
一个UINavigationControllerDelegate
。此视图控制器将自身设置为导航控制器的委托,并返回允许的方向。在我的情况下,默认情况下允许所有方向,首选纵向,但在一个特定情况下,只允许纵向。下面的代码来自Swift 3 / XCode 8:
class iPhoneStartViewController: UIViewController {
var navInterfaceOrientationMask: UIInterfaceOrientationMask?
var navInterfaceOrientationPreferred: UIInterfaceOrientation! = .portrait
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.delegate = self
}
@IBAction func cameraButtonPressed(_ sender: AnyObject) {
if PermissionsHelper.singleton().photosPermissionGranted() == false {
self.navInterfaceOrientationMask = nil // default is: all orientations supported
self.performSegue(withIdentifier: "segueToPhotoAccess", sender: self)
} else {
self.navInterfaceOrientationMask = .portrait // this stops the next view controller from being to rotate away from portrait
self.performSegue(withIdentifier: "segueToCamera", sender: self)
}
}
}
// lock orientation to portrait in certain cases only. Default is: all orientations supported
extension iPhoneStartViewController : UINavigationControllerDelegate {
public func navigationControllerSupportedInterfaceOrientations(_ navigationController: UINavigationController) -> UIInterfaceOrientationMask {
if let mask = self.navInterfaceOrientationMask {
return mask
} else {
return .all
}
}
public func navigationControllerPreferredInterfaceOrientationForPresentation(_ navigationController: UINavigationController) -> UIInterfaceOrientation {
return self.navInterfaceOrientationPreferred
}
}
答案 9 :(得分:0)
我有同样的情况。所以我将UINavigationController子类化为CustomNavigationController,在这个CustomNavigationController里面,我写了
#define IOS_OLDER_THAN_6 ( [ [ [ UIDevice currentDevice ] systemVersion ] floatValue ] < 6.0 )
#define IOS_NEWER_OR_EQUAL_TO_6 ( [ [ [ UIDevice currentDevice ] systemVersion ] floatValue ] >= 6.0 )
#pragma mark - Rotation
#ifdef IOS_OLDER_THAN_6
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{
return (toInterfaceOrientation == UIInterfaceOrientationPortrait);
}
#endif
#ifdef IOS_NEWER_OR_EQUAL_TO_6
-(BOOL)shouldAutorotate {
return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskPortrait;;
}
#endif
我使用了这个CustomNavigationController而不是现有的NavigationController。
然后在你必须在LandScape Orientation中显示的视图控制器里面说LandScapeView,我写了
#pragma mark - Rotation
#ifdef IOS_OLDER_THAN_6
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{
return (toInterfaceOrientation == UIInterfaceOrientationLandscapeRight | toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft);
}
#endif
#ifdef IOS_NEWER_OR_EQUAL_TO_6
-(BOOL)shouldAutorotate {
return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskLandscapeLeft;
}
#endif
在CustomNavigationController中,我提出了这个视图控制器,没有推入导航堆栈。所以LandScapeView出现在LandScape Orientation。
LandScapeView *graph = [[LandScapeView alloc]init....];
[self presentViewController:graph animated:YES completion:nil];
我没有更改项目设置中支持的界面方向中的任何内容。
答案 10 :(得分:0)
//在app deligate类中粘贴此方法
- (UIInterfaceOrientationMask)application:(UIApplication )application supportedInterfaceOrientationsForWindow:(UIWindow )window
{
if ([self.window.rootViewController.presentedViewController isKindOfClass: [_moviePlayerController class]])
{
if (self.window.rootViewController.presentedViewController)
return UIInterfaceOrientationMaskAll;
else return UIInterfaceOrientationMaskPortrait;
}
else return UIInterfaceOrientationMaskPortrait;
}
答案 11 :(得分:0)
如果应用程序支持从 IOS7 到 IOS9 ,请使用此代码进行定位:
#if __IPHONE_OS_VERSION_MAX_ALLOWED < 90000
- (NSUInteger)supportedInterfaceOrientations
#else
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
#endif
{
if([AppDelegate isPad]) return UIInterfaceOrientationMaskAll;
else return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown;
}
答案 12 :(得分:0)
我知道这些问题已经很老了但需要更新的答案。实现此结果的最简单,最正确的方法是在应用程序设置中启用纵向和横向。然后将此代码添加到您的应用代理:
func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> UIInterfaceOrientationMask {
if let navigationController = self.window?.rootViewController as? UINavigationController {
if navigationController.visibleViewController is INSERTYOURVIEWCONTROLLERHERE {
return UIInterfaceOrientationMask.All
}
else {
return UIInterfaceOrientationMask.Portrait
}
}
return UIInterfaceOrientationMask.Portrait
}
别忘了用视图控制器替换“INSERTYOURVIEWCONTROLLERHERE”。