私のアプリはiphone
デバイス(iphone 4と5の両方)専用であり、ios 6
。
私のアプリ全体はportrait
モードのみをサポートしています。しかし、「ChatView
」というビューが1つあり、landscape
モードとportrait
モードの両方をサポートしたいと考えています。
必要なデバイスの回転を次のように設定しました-
また、「ChatView」で回転をサポートするために次のコードを試してみました-
-(BOOL)shouldAutorotate
{
return YES;
}
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscape;
}
しかし、そのビューを回転させることはできませんでした。
私はこれを多く検索しましたが、私の問題の解決策を見つけることができませんでした。
また、「ChatView」には、ボタン、フレームがプログラムで設定されるテキストフィールドなどのオブジェクトがあります。だから私はまた、ランドスケープモードのためにそれらのすべてのオブジェクトのフレームを設定する必要があるのか知りたいですか?
私を助けてください。
ありがとう.....
ViewControllerの回転を1つだけサポートしたい場合、アプリケーションは.plist
ファイル。別の方法として、アプリを横向きと縦向きの両方でサポートし、チャットビューを除くすべてのViewControllerの回転を縦向きに固定する方法があります。
[〜#〜] edit [〜#〜]
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に役立つことを願っています。
シンプルですが、非常にうまく機能します。 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
View Controllerは、アプリ自体でサポートされていない位置に回転することはありません。可能なすべての回転を有効にしてから、回転するはずのないView Controllerで次の行を配置する必要があります
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
ChatViewでは、次のようになります。
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskAll;
}
回転後にレイアウトを変更する必要がある場合は、サブビューに適切な変更を実装する必要があります
- (void)viewWillLayoutSubviews
つかいます self.view.bounds
は、view
の現在のサイズを確認します。self.view.frame
は回転後も変化しません。
特定の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;
}
}
テッドの答えは、ノルウェーのアレキサンダーが言及した問題とうまく機能します。しかし、私はアレクサンダーが説明したように問題が起こっていないことを理解しました、
現在横向き(すべての方向が有効)になっているViewController BがViewController Aに戻ると(ユーザーが戻るボタンをクリックした後、supportedInterfaceOrientationsForWindowは呼び出されず、ViewController Aは横向きになります)
実際に、ユーザーが戻るボタンをクリックした後、現在横向きになっているViewController B(すべての方向が有効)がViewController A(縦のみ)に戻るとき、Appdelegate
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation;
呼ばれています。ただし、ルートView ControllerはViewController B(回転対応View Controller)ですが、ViewController Bはまだ戻っているため、ViewController Aは縦向きに戻りません。
-(BOOL)shouldAutorotate{
return YES;
}
戻るボタンを押すと、ViewController Bで「shouldAutorotate-> NO」が返されます。ViewControllerAは縦向きになります。これは私がやったことです
@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;
}
Swift 3コーシャバージョン
誰かが問題を抱えている場合のために、これをここに残しました。
Appleのドキュメント for supportedInterfaceOrientations
のコメント:
ユーザーがデバイスの向きを変更すると、システムは、ルートビューコントローラーまたはウィンドウを埋める最上部に表示されるビューコントローラーでこのメソッドを呼び出します。 View Controllerが新しい方向をサポートしている場合、ウィンドウとView Controllerは新しい方向に回転します。このメソッドは、View ControllerのshouldAutorotateメソッドがtrueを返す場合にのみ呼び出されます。
簡単に言うと、ルートビューコントローラーのsupportedInterfaceOrientations
をオーバーライドして、最上位の子ビューコントローラーの値とそれ以外のデフォルト値を返す必要があります。
あなたがすべきことは、アプリがすべてのモードをサポートしているかどうかを確認することです(ターゲットの一般設定またはInfo.plistの展開情報に移動します)、ルートView Controllerのクラスを見つけます。汎用UIViewController、UINavigationController、UITabBarControllerまたはカスタムクラスのいずれかです。次の方法で確認できます。
dump(UIApplication.shared.keyWindow?.rootViewController)
またはあなたが好きな他の方法。
いくつかのCustomNavigationController
にします。したがって、次のようにsupportedInterfaceOrientations
をオーバーライドする必要があります。
class CustomNavigationController: UINavigationController {
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return topViewController?.supportedInterfaceOrientations ?? .allButUpsideDown
}
}
インスタンスのポートレート方向のみをサポートするView Controllerでは、次のようにsupportedInterfaceOrientations
をオーバーライドします。
class ChildViewController: UIViewController {
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return .portrait
}
}
次に、ルートView Controllerと最上位にあるView ControllerのshouldAutorotate
がすでにtrue
を返しているかどうかを確認することを忘れないでください。そうでない場合、これをクラス定義に追加します。
override var shouldAutorotate: Bool {
return true
}
それ以外の場合、supportedInterfaceOrientations
はまったく呼び出されません。
どうぞ!
1つのView Controllerのみが多数の方向をサポートし、他のView Controllerはサポートしないという反対の問題を修正する必要がある場合は、この変更をすべてのView Controllerに加えてください。
これが役立つことを願っています。
この問題の歴史についてはわかりませんが(現在= iOS 10の期間)、これを投稿したときに最も簡単な解決策がありませんでした 2016年10月。
これが欲しいと仮定すると:
UINavigationController
sを追加せずに追加することをサポート...次に(IMO)最も簡単な解決策はINavigationControllerDelegateを作成で、サブクラスUINavigationControllerではありません(上記の前提4に違反します)。
これを解決したとき、私の最初のViewController
a UINavigationControllerDelegate
にすることにしました。このView Controllerは、それ自体をNavigation Controllerのデリゲートとして設定し、許可されている方向を返します。私の場合、デフォルトではすべての方向が許可され、ポートレートが優先されますが、特定のケースではポートレートのみが許可されます。以下のコードは、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
}
}
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
ビューコントローラーの名前がServicesVCであると仮定します
@iAnumの回答に基づいて、自動回転とUIViewControllerクラスの検出を有効にしました。
これは、そうしないと「特別なView Controller」に出入りするのが縦向きに修正されず、サポートされていない向きで立ち往生するためです。
ランドスケープをサポートするビューは1つしかなかったため、カスタムNavigation View Controllerでハードコーディングしました。
-(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);
}
ここで説明されているVCのポップに問題があります 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:^{
}];
}];
}
}
SwiftのAlexander( 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
}}
また、すべての回転を許可するViewControllerの場合、次の関数を追加します。
override func canAutoRotate() -> Bool {
return true
}
//このメソッドをアプリデリゲートクラスに貼り付けます
- (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;
}
アプリがIOS7からIOS9をサポートしている場合、オリエンテーションにこのコードを使用します。
#if __IPHONE_OS_VERSION_MAX_ALLOWED < 90000
- (NSUInteger)supportedInterfaceOrientations
#else
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
#endif
{
if([AppDelegate isPad]) return UIInterfaceOrientationMaskAll;
else return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown;
}
この質問は非常に古いものですが、更新された回答が必要です。この結果を達成する最も簡単で最も正しい方法は、アプリの設定でポートレートとランドスケープを有効にすることです。次に、このコードをアプリのデリゲートに追加します。
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」をView Controllerに置き換えることを忘れないでください。
私も同じ状況でした。そこで、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
既存のNavigationControllerではなく、このCustomNavigationControllerを使用しました。
次に、LandScape Orientationに表示する必要があるView Controller内で、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内で、Navigation Stackにプッシュされるのではなく、このView Controllerを提示しました。そのため、LandScapeViewはLandScape Orientationに表示されました。
LandScapeView *graph = [[LandScapeView alloc]init....];
[self presentViewController:graph animated:YES completion:nil];
プロジェクト設定のサポートされているインターフェイスの向きで何も変更しませんでした。