Ras*_*ick 144 objective-c uinavigationcontroller autorotate ios ios8
在iOS 8之前,我们将下面的代码与supportedInterfaceOrientations和shouldAutoRotate委托方法结合使用,以强制应用程序方向指向任何特定方向.我使用下面的代码段以编程方式将应用程序旋转到所需的方向.首先,我正在改变状态栏方向.然后只显示并立即关闭模态视图会将视图旋转到所需的方向.
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:YES];
UIViewController *c = [[UIViewController alloc]init];
[self presentViewController:vc animated:NO completion:nil];
[self dismissViewControllerAnimated:NO completion:nil];
Run Code Online (Sandbox Code Playgroud)
但这在iOS 8中失败了.而且,我已经看到堆栈溢出的一些答案,人们建议我们应该始终从iOS 8开始避免这种方法.
更具体地说,我的应用程序是一种通用类型的应用程序.总共有三个控制器.
First View控制器 - 它应该支持iPad中的所有方向,并且只支持iPhone中的纵向(主页按钮).
第二视图控制器 - 它应该只支持所有条件下的横向
第三视图控制器 - 它应该只支持所有条件下的风景
我们使用导航控制器进行页面导航.从第一个视图控制器,在按钮单击操作上,我们在堆栈上推送第二个.因此,当第二个视图控制器到达时,无论设备方向如何,应用程序都应仅锁定横向.
下面是我shouldAutorotate和supportedInterfaceOrientations第二和第三视图控制器中的方法.
-(NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskLandscapeRight;
}
-(BOOL)shouldAutorotate {
return NO;
}
Run Code Online (Sandbox Code Playgroud)
对于这种或任何更好的方法来锁定iOS 8的特定方向的视图控制器是否有任何解决方案.请帮忙!!
Sun*_*hah 305
对于iOS 7 - 10:
Objective-C的:
[[UIDevice currentDevice] setValue:@(UIInterfaceOrientationLandscapeLeft) forKey:@"orientation"];
[UINavigationController attemptRotationToDeviceOrientation];
Run Code Online (Sandbox Code Playgroud)
斯威夫特3:
let value = UIInterfaceOrientation.landscapeLeft.rawValue
UIDevice.current.setValue(value, forKey: "orientation")
UINavigationController.attemptRotationToDeviceOrientation()
Run Code Online (Sandbox Code Playgroud)
只需- viewDidAppear:在显示的视图控制器中调用它.
Kor*_*ton 92
如果你在一个UINavigationController或多个里面,方向旋转会有点复杂UITabBarController.问题是如果视图控制器嵌入其中一个控制器中,导航或标签栏控制器优先,并决定自动旋转和支持的方向.
我在UINavigationController和UITabBarController上使用以下2个扩展,以便嵌入其中一个控制器的视图控制器可以做出决定.
斯威夫特2.3
extension UINavigationController {
public override func supportedInterfaceOrientations() -> Int {
return visibleViewController.supportedInterfaceOrientations()
}
public override func shouldAutorotate() -> Bool {
return visibleViewController.shouldAutorotate()
}
}
extension UITabBarController {
public override func supportedInterfaceOrientations() -> Int {
if let selected = selectedViewController {
return selected.supportedInterfaceOrientations()
}
return super.supportedInterfaceOrientations()
}
public override func shouldAutorotate() -> Bool {
if let selected = selectedViewController {
return selected.shouldAutorotate()
}
return super.shouldAutorotate()
}
}
Run Code Online (Sandbox Code Playgroud)
斯威夫特3
extension UINavigationController {
open override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return visibleViewController?.supportedInterfaceOrientations ?? super.supportedInterfaceOrientations
}
open override var shouldAutorotate: Bool {
return visibleViewController?.shouldAutorotate ?? super.shouldAutorotate
}
}
extension UITabBarController {
open override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
if let selected = selectedViewController {
return selected.supportedInterfaceOrientations
}
return super.supportedInterfaceOrientations
}
open override var shouldAutorotate: Bool {
if let selected = selectedViewController {
return selected.shouldAutorotate
}
return super.shouldAutorotate
}
}
Run Code Online (Sandbox Code Playgroud)
现在您可以覆盖该supportedInterfaceOrientations方法,或者您可以shouldAutoRotate在要锁定的视图控制器中覆盖,否则您可以忽略其他视图控制器中要覆盖应用程序plist中指定的默认方向行为的覆盖
class ViewController: UIViewController {
override func shouldAutorotate() -> Bool {
return false
}
}
Run Code Online (Sandbox Code Playgroud)
class ViewController: UIViewController {
override func supportedInterfaceOrientations() -> Int {
return Int(UIInterfaceOrientationMask.Landscape.rawValue)
}
}
Run Code Online (Sandbox Code Playgroud)
从理论上讲,这应该适用于所有复杂的视图控制器层次结构,但我注意到UITabBarController存在问题.出于某种原因,它想要使用默认方向值.如果您有兴趣了解如何解决某些问题,请参阅以下博文:
Vin*_*hop 23
这对我有用:
在viewDidAppear:方法中调用它.
- (void) viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[UIViewController attemptRotationToDeviceOrientation];
}
Run Code Online (Sandbox Code Playgroud)
小智 20
我发现如果它是一个呈现的视图控制器,你可以覆盖 preferredInterfaceOrientationForPresentation
迅速:
override func supportedInterfaceOrientations() -> Int {
return Int(UIInterfaceOrientationMask.Landscape.rawValue)
}
override func preferredInterfaceOrientationForPresentation() -> UIInterfaceOrientation {
return UIInterfaceOrientation.LandscapeLeft
}
override func shouldAutorotate() -> Bool {
return false
}
Run Code Online (Sandbox Code Playgroud)
Ale*_*ano 15
这种方式适用于Swift 2 iOS 8.x:
PS(这种方法不需要在每个viewController上覆盖定向函数,比如shouldautorotate,只需要AppDelegate上的一个方法)
所以,在AppDelegate.swift上创建一个变量:
var enableAllOrientation = false
Run Code Online (Sandbox Code Playgroud)
所以,还把这个功能:
func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> UIInterfaceOrientationMask {
if (enableAllOrientation == true){
return UIInterfaceOrientationMask.All
}
return UIInterfaceOrientationMask.Portrait
}
Run Code Online (Sandbox Code Playgroud)
因此,在项目的每个类中,您都可以在viewWillAppear中设置此var:
override func viewWillAppear(animated: Bool)
{
super.viewWillAppear(animated)
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
appDelegate.enableAllOrientation = true
}
Run Code Online (Sandbox Code Playgroud)
如果您需要根据设备类型进行选择,可以执行以下操作:
override func viewWillAppear(animated: Bool)
{
super.viewWillAppear(animated)
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
switch UIDevice.currentDevice().userInterfaceIdiom {
case .Phone:
// It's an iPhone
print(" - Only portrait mode to iPhone")
appDelegate.enableAllOrientation = false
case .Pad:
// It's an iPad
print(" - All orientation mode enabled on iPad")
appDelegate.enableAllOrientation = true
case .Unspecified:
// Uh, oh! What could it be?
appDelegate.enableAllOrientation = false
}
}
Run Code Online (Sandbox Code Playgroud)
gbk*_*gbk 11
首先 - 这是一个坏主意,一般来说,您的应用程序架构出现问题,但是sh..t happens,如果是这样,您可以尝试制作如下内容:
final class OrientationController {
static private (set) var allowedOrientation:UIInterfaceOrientationMask = [.all]
// MARK: - Public
class func lockOrientation(_ orientationIdiom: UIInterfaceOrientationMask) {
OrientationController.allowedOrientation = [orientationIdiom]
}
class func forceLockOrientation(_ orientation: UIInterfaceOrientation) {
var mask:UIInterfaceOrientationMask = []
switch orientation {
case .unknown:
mask = [.all]
case .portrait:
mask = [.portrait]
case .portraitUpsideDown:
mask = [.portraitUpsideDown]
case .landscapeLeft:
mask = [.landscapeLeft]
case .landscapeRight:
mask = [.landscapeRight]
}
OrientationController.lockOrientation(mask)
UIDevice.current.setValue(orientation.rawValue, forKey: "orientation")
}
}
Run Code Online (Sandbox Code Playgroud)
比,在 AppDelegate
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// do stuff
OrientationController.lockOrientation(.portrait)
return true
}
// MARK: - Orientation
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
return OrientationController.allowedOrientation
}
Run Code Online (Sandbox Code Playgroud)
每当你想改变方向时,请执行以下操作:
OrientationController.forceLockOrientation(.landscapeRight)
Run Code Online (Sandbox Code Playgroud)
注意:有时,设备可能无法通过此类呼叫进行更新,因此您可能需要执行以下操作
OrientationController.forceLockOrientation(.portrait)
OrientationController.forceLockOrientation(.landscapeRight)
Run Code Online (Sandbox Code Playgroud)
就这样
这应该从iOS 6开始向上,但我只在iOS 8上测试它.子类UINavigationController并覆盖以下方法:
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return UIInterfaceOrientationLandscapeRight;
}
- (BOOL)shouldAutorotate {
return NO;
}
Run Code Online (Sandbox Code Playgroud)
或询问可见的视图控制器
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return self.visibleViewController.preferredInterfaceOrientationForPresentation;
}
- (BOOL)shouldAutorotate {
return self.visibleViewController.shouldAutorotate;
}
Run Code Online (Sandbox Code Playgroud)
并在那里实施方法.
这是对Sid Shah的回答中的评论的反馈,关于如何使用以下方法禁用动画:
[UIView setAnimationsEnabled:enabled];
Run Code Online (Sandbox Code Playgroud)
码:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:NO];
[UIView setAnimationsEnabled:NO];
// Stackoverflow #26357162 to force orientation
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeRight];
[[UIDevice currentDevice] setValue:value forKey:@"orientation"];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:NO];
[UIView setAnimationsEnabled:YES];
}
Run Code Online (Sandbox Code Playgroud)
如果您使用的是navigationViewController,则应为此创建自己的超类并覆盖:
- (BOOL)shouldAutorotate {
id currentViewController = self.topViewController;
if ([currentViewController isKindOfClass:[SecondViewController class]])
return NO;
return YES;
}
Run Code Online (Sandbox Code Playgroud)
这将禁用SecondViewController中的旋转,但如果您在设备处于纵向方向时按下SecondViewController,则SecondViewController将以纵向模式显示.
假设您正在使用故事板.您必须在"onClick"方法中创建手动segue(如何):
- (IBAction)onPlayButtonClicked:(UIBarButtonItem *)sender {
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft];
[[UIDevice currentDevice] setValue:value forKey:@"orientation"];
[self performSegueWithIdentifier:@"PushPlayerViewController" sender:self];
}
Run Code Online (Sandbox Code Playgroud)
这将在您的超类禁用自动旋转功能之前强制横向方向.
在Xcode 8方法转换为属性,因此以下工作Swift:
override public var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return UIInterfaceOrientationMask.portrait
}
override public var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
return UIInterfaceOrientation.portrait
}
override public var shouldAutorotate: Bool {
return true
}
Run Code Online (Sandbox Code Playgroud)