Cách buộc UIViewController theo hướng dọc trong iOS 6


85

Khi ShouldAutorotateToInterfaceOrientationbị phản đối trong iOS 6 và tôi sử dụng mà để buộc một cái nhìn đặc biệt đến chân dung duy nhất , cách chính xác để làm điều này trong iOS 6 là bao nhiêu? Điều này chỉ dành cho một khu vực trong ứng dụng của tôi, tất cả các chế độ xem khác đều có thể xoay vòng.

Câu trả lời:


117

Nếu bạn muốn tất cả các bộ điều khiển điều hướng của chúng tôi tôn trọng bộ điều khiển chế độ xem trên cùng, bạn có thể sử dụng một danh mục để bạn không phải thực hiện và thay đổi một loạt các tên lớp.

@implementation UINavigationController (Rotation_IOS6)

-(BOOL)shouldAutorotate
{
    return [[self.viewControllers lastObject] shouldAutorotate];
}

-(NSUInteger)supportedInterfaceOrientations
{
    return [[self.viewControllers lastObject] supportedInterfaceOrientations];
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
    return [[self.viewControllers lastObject] preferredInterfaceOrientationForPresentation];
}

@end

Như một số nhận xét đã chỉ ra, đây là một cách khắc phục nhanh chóng cho sự cố. Một giải pháp tốt hơn là phân lớp UINavigationController và đặt các phương thức này ở đó. Một lớp con cũng giúp hỗ trợ 6 và 7.


3
Tôi có thể xác nhận điều này hoạt động. Bạn cũng có thể thay thế "[self.viewControllers lastObject]" bằng "self.topViewController" nếu muốn.
Wayne Liu

3
Nếu bạn đang sử dụng UITabBarController hơn danh mục UINavigationController này thì không giúp được gì. Bạn nên thực hiện mục trên UITabBarController thay ...
Borut Tomazin

46
Vấn đề với giải pháp này là nó không hoạt động khi bạn bật bộ điều khiển nằm ngang và bộ điều khiển hàng đầu mới của bạn chỉ hỗ trợ dọc (hoặc ngược lại), những lệnh gọi lại đó không được gọi trong trường hợp này và tôi vẫn chưa tìm ra cách buộc bộ điều khiển hàng đầu mới vào đúng hướng. Có ý kiến ​​gì không?
Lope

4
Tôi đã phân lớp phụ UINavigationController và đặt nó là window.rootController. Tôi thực hiện tất cả 3 phương pháp, nó hoạt động tuyệt vời khi bạn thay đổi chuyển động quay của thiết bị, vấn đề là các phương pháp đó (và không có gì liên quan đến luân phiên) được gọi khi bạn bật view controller
Lope

4
Nếu tôi đang thực hiện đẩy hoặc bật từ bộ điều khiển chế độ xem ngang thì lực này UIViewController sẽ thay đổi thành Cảnh quan. Tuy nhiên, nếu tôi xoay thành dọc thì nó hoạt động tốt và nó sẽ không bao giờ thay đổi thành ngang. Vấn đề duy nhất khi đẩy hoặc bật từ ngang. Vui lòng giúp đỡ
Tariq

63

Cách tốt nhất cho iOS6 cụ thể được ghi nhận trong "Hướng dẫn sử dụng iOS6" của nhóm Ray Wenderlich - http://www.raywenderlich.com/ và tốt hơn là phân lớp UINavigationControllercho hầu hết các trường hợp.

Tôi đang sử dụng iOS6 với bảng phân cảnh bao gồm một UINavigationControllerbộ làm bộ điều khiển chế độ xem ban đầu.

//AppDelegate.m - rất tiếc phương pháp này không khả dụng trước iOS6

- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
NSUInteger orientations = UIInterfaceOrientationMaskAllButUpsideDown;

if(self.window.rootViewController){
    UIViewController *presentedViewController = [[(UINavigationController *)self.window.rootViewController viewControllers] lastObject];
    orientations = [presentedViewController supportedInterfaceOrientations];
}

return orientations;
}

//MyViewController.m - trả về bất kỳ định hướng nào bạn muốn hỗ trợ cho từng UIViewController

- (NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskPortrait;
}

1
Đây là giải pháp tốt nhất cho iOS 6
Homam,

2
@Phil, Nó hoạt động tốt cho iOS 6. Nhưng trong một số trường hợp, chẳng hạn như nếu bạn chuyển từ ngang sang dọc thì nó không hoạt động. Bất kỳ ý tưởng tại sao nó xảy ra?
Kirti Nikam

1
Giải pháp rất hữu ích. Đối với tôi, tốt nhất.
oscar castellon

1
Hoạt động trên iOS 7 beta 6. Hoạt động khi chuyển từ ngang sang dọc trong trường hợp của tôi.
Martin Berger

Tôi đang sử dụng iOS 6 nhưng điều này không hoạt động. Nó bị hỏng trên dòng "UIViewController * presentViewController".
Marcel Marino,

39

Câu trả lời này liên quan đến các câu hỏi được hỏi trong phần bình luận của bài đăng của OP:

Để buộc một chế độ xem xuất hiện theo một định hướng nhất định, hãy đặt những điều sau vào chế độ xemWillAppear:

UIApplication* application = [UIApplication sharedApplication];
if (application.statusBarOrientation != UIInterfaceOrientationPortrait)
{
    UIViewController *c = [[UIViewController alloc]init];
    [self presentModalViewController:c animated:NO];
    [self dismissModalViewControllerAnimated:NO];
}

Đó là một chút hack, nhưng điều này buộc UIViewControllerphải được trình bày ở dạng dọc ngay cả khi bộ điều khiển trước đó là ngang

CẬP NHẬT cho iOS7

Các phương pháp trên hiện không được dùng nữa, vì vậy đối với iOS 7, hãy sử dụng các phương pháp sau:

UIApplication* application = [UIApplication sharedApplication];
if (application.statusBarOrientation != UIInterfaceOrientationPortrait)
{
     UIViewController *c = [[UIViewController alloc]init];
     [c.view setBackgroundColor:[UIColor redColor]];
     [self.navigationController presentViewController:c animated:NO completion:^{
            [self.navigationController dismissViewControllerAnimated:YES completion:^{
            }];
     }];
}

Điều thú vị là, tại thời điểm viết bài, hoặc là hiện tại hoặc sa thải phải được hoạt hình. Nếu cả hai đều không, thì bạn sẽ nhận được một màn hình trắng. Không hiểu tại sao điều này làm cho nó hoạt động, nhưng nó có! Hiệu ứng hình ảnh khác nhau tùy thuộc vào hoạt ảnh.


Cảm ơn, tôi sẽ dùng thử khi tôi có vài phút rảnh rỗi
Lope

@RohanAgarwal nó hoạt động như quảng cáo, tôi đang sử dụng nó ở đây. Nhưng bạn cũng cần phải triển khai mã của câu trả lời được chấp nhận, nếu không nó sẽ không hoạt động.
Dennis Munsie

2
Có ai đã tìm ra cách để làm cho điều này hoạt động với hoạt ảnh xoay chính xác cùng một lúc? Hơi chói tai khi thấy nó chuyển từ dọc sang ngang mà không có hoạt ảnh. Nó hoạt động, chỉ hy vọng làm cho nó hoạt động tốt hơn một chút.
Dennis Munsie

@Craig Watkinson Nó không hoạt động trong bảng phân cảnh. và presentModalViewController và dismissModalViewControllerAnimated bị phản đối nếu iam sử dụng presentVirecontroller sau đó nó sẽ không làm việc giúp đỡ Xin vui lòng cho tôi
Kalpesh

1
Đối với ios8 allowViewControllerAnimated chỉ bị treo. Tôi thấy rằng việc gọi [NWSAppDelegate sharedInstance] .window.rootViewController = nil; [NWSAppDelegate sharedInstance] .window.rootViewController = beforeRootController hoạt động tốt.
Alexey

36

Vì vậy, tôi đã gặp phải vấn đề tương tự khi chỉ hiển thị chế độ xem dọc theo phương thức. Thông thường, tôi sẽ tạo một UINavigationController, đặt viewControllerrootViewController, sau đó hiển thị UINavigationControllerdưới dạng chế độ xem phương thức. Nhưng với iOS 6, viewControllerbây giờ sẽ yêu cầu điều hướngController về các hướng giao diện được hỗ trợ của nó (theo mặc định, bây giờ là tất cả cho iPad và mọi thứ trừ ngược cho iPhone).

Giải pháp : Tôi đã phải phân lớp UINavigationControllervà ghi đè các phương thức tự động chuyển đổi. Loại khập khiễng.

- (BOOL)shouldAutorotate {
    return NO;
}

- (NSUInteger)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskPortrait;
}
// pre-iOS 6 support 
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    return (toInterfaceOrientation == UIInterfaceOrientationPortrait);
}

1
không hoạt động trên của tôi. Tôi có mã này với toàn cầu setted cho tất cả các định hướng
phil88530

2
SupportInterfaceOrientations phải trả về NSUInteger, không phải BOOL. Xem developer.apple.com/library/ios/#featuredarticles/…
tomwhipple

làm việc của nó, đối với tôi nó là tabbarcontroller, một lần nữa cảm ơn cho câu trả lời
otakuProgrammer

FWIW, tôi cũng phải đi con đường này ... Không có gì khác hoạt động. Cảm ơn.
Steve N

15

IOS 5

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{

    return (interfaceOrientation == UIInterfaceOrientationPortrait);

}

hệ điều hanh 6

-(BOOL)shouldAutorotate{
    return YES;
}

-(NSInteger)supportedInterfaceOrientations{

    //    UIInterfaceOrientationMaskLandscape;
    //    24
    //
    //    UIInterfaceOrientationMaskLandscapeLeft;
    //    16
    //
    //    UIInterfaceOrientationMaskLandscapeRight;
    //    8
    //
    //    UIInterfaceOrientationMaskPortrait;
    //    2

    //    return UIInterfaceOrientationMaskPortrait; 
    //    or
          return 2;
}

Thông minh! Cần phải tối đa ở đầu chủ đề này. Bởi vì nó là đơn giản nhất cách giải quyết vấn đề
Alex

@Roshan Jalgaonkar trong iOS 6 Nó không làm việc cho tôi tôi chỉ cần chân dung với xuống nút home làm thế nào tôi có thể thiết lập UIOrientation này ....
Karthik

@Karthik, bạn phải bật các cách xoay được hỗ trợ trong mục tiêu của Ứng dụng để điều này hoạt động.
Alejandro Iván

@ AlejandroIván k thnx
Karthik

10

Tôi không đồng ý với câu trả lời @aprato, bởi vì các phương thức xoay vòng UIViewController được khai báo trong chính danh mục, do đó dẫn đến hành vi không xác định nếu bạn ghi đè sau đó trong danh mục khác. An toàn hơn khi ghi đè chúng trong một lớp con UINavigationController (hoặc UITabBarController)

Ngoài ra, điều này không bao gồm trường hợp bạn đẩy / trình bày / bật từ chế độ xem Phong cảnh thành một VC chỉ dọc hoặc ngược lại. Để giải quyết vấn đề khó khăn này (chưa từng được Apple giải quyết), bạn nên:

Trong iOS <= 4 và iOS> = 6:

UIViewController *vc = [[UIViewController alloc]init];
[self presentModalViewController:vc animated:NO];
[self dismissModalViewControllerAnimated:NO];
[vc release];

Trong iOS 5:

UIWindow *window = [[UIApplication sharedApplication] keyWindow];
UIView *view = [window.subviews objectAtIndex:0];
[view removeFromSuperview];
[window addSubview:view];

Những điều này THỰC SỰ sẽ buộc UIKit phải đánh giá lại tất cả các shouldAutorotate, hỗ trợInterfaceOrientations, v.v.


2
Sự cố đầu tiên trong số những sự cố này đối với tôi bất kể phiên bản iOS. Loại bỏ nói không nên được gọi trước khi hiện tại kết thúc.
arsenius

@arsenius Bạn có thể đăng đoạn trích về cách bạn đang sử dụng nó không? Chừng nào nó không phải là hoạt hình nó không nên có vấn đề bạn đề cập đến
Rafael Nobre

Tôi cũng đặt đoạn thứ hai vào viewDidAppear và nó không làm gì để giúp đỡ hoàn cảnh của tôi trên iOS 6. Câu hỏi là ở đây: stackoverflow.com/questions/15654339/...
arsenius

Xin lỗi, một bình luận cuối cùng ở đây. Di chuyển mã iOS 5 sang viewDidAppear sẽ tạo ra một số loại vòng lặp vô hạn với đầu ra này: - [UIApplication beginIgnoringInteractionEvents] tràn. Làm ngơ.
arsenius

3

Tôi có một cách tiếp cận rất tốt là trộn https://stackoverflow.com/a/13982508/2516436https://stackoverflow.com/a/17578272/2516436

-(NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
    NSUInteger orientations = UIInterfaceOrientationMaskAllButUpsideDown;


    if(self.window.rootViewController){
        UIViewController *presentedViewController = [self topViewControllerWithRootViewController:self.window.rootViewController];
        orientations = [presentedViewController supportedInterfaceOrientations];
    }

    return orientations;
}

- (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;
    }
}

và trả lại bất kỳ định hướng nào bạn muốn hỗ trợ cho từng UIViewController

- (NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskPortrait;
}

1

Tôi có một ứng dụng phổ dụng tương đối phức tạp bằng cách sử dụng UISplitViewController và UISegmentedController và có một vài chế độ xem phải được trình bày trong Chế độ xem bằng cách sử dụng presentViewController. Sử dụng các phương pháp được đề xuất ở trên, tôi đã có thể làm cho iPhone ios 5 & 6 hoạt động ở mức chấp nhận được, nhưng vì một số lý do mà iPad chỉ từ chối hiển thị là Cảnh. Cuối cùng, tôi đã tìm thấy một giải pháp đơn giản (được thực hiện sau hàng giờ đọc và thử và sai) hoạt động cho cả thiết bị và ios 5 & 6.

Bước 1) Trên bộ điều khiển, chỉ định hướng cần thiết (nhiều hơn hoặc ít hơn như đã lưu ý ở trên)

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}

-(BOOL)shouldAutorotate
{
    return YES;
}

-(NSUInteger)supportedInterfaceOrientations
{
    NSInteger mask = UIInterfaceOrientationMaskLandscape;
    return mask;

}

Bước 2) Tạo một lớp con UINavigationController đơn giản và triển khai các phương pháp sau

-(BOOL)shouldAutorotate {
        return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
        return UIInterfaceOrientationMaskLandscape;
}

Bước 3) Trình bày chế độ xem của bạn

vc = [[MyViewController alloc]init];
MyLandscapeNavigationController *myNavigationController = [[MyLandscapeNavigationController alloc] initWithRootViewController:vc];
[self myNavigationController animated:YES completion:nil];

Hy vọng điều này là hữu ích cho ai đó.


1

Không phải là buồn tẻ ở đây, nhưng bạn có vui lòng chia sẻ lớp con của mình không? Cảm ơn bạn.

chỉnh sửa: tốt, cuối cùng tôi đã làm được, lớp con đã chết đơn giản để làm. Tôi chỉ cần khai báo navigationControllerAppDelegatedạng UINavigationControllerSubclassthay vì mặc định UINavigationController, sau đó sửa đổi lớp con của bạn bằng:

- (BOOL)shouldAutorotate {
    return _shouldRotate;
}

vì vậy tôi có thể đặt bất kỳ chế độ xem nào tôi muốn xoay hoặc không bằng cách gọi theo số viewDidLoad

_navController = (UINavigationController *)self.navigationController;
[_navController setShouldRotate : YES / NO]

Hy vọng chỉnh sửa này cũng sẽ giúp ích cho những người khác, cảm ơn mẹo của bạn!

Mẹo: Tận dụng

- (NSUInteger)supportedInterfaceOrientations

trong bộ điều khiển chế độ xem của bạn, vì vậy bạn không thể có chế độ xem dọc mong muốn ở chế độ ngang hoặc ngược lại.


0

Tôi đã không tự mình kiểm tra nó, nhưng tài liệu nói rằng bây giờ bạn có thể ghi đè các phương thức đó: supportedInterfaceOrientationspreferredInterfaceOrientationForPresentation.

Bạn có thể đạt được những gì bạn muốn y chỉ thiết lập hướng bạn muốn trong các phương pháp đó.


0

Các câu trả lời sử dụng các lớp con hoặc danh mục để cho phép các VC trong các lớp UINavigationController và UITabBarController hoạt động tốt. Không khởi chạy được phương thức chỉ dọc từ bộ điều khiển thanh tab ngang. Nếu bạn cần thực hiện việc này, hãy sử dụng thủ thuật hiển thị và ẩn chế độ xem phương thức không động, nhưng hãy thực hiện trong phương thức viewDidAppear . Nó không hoạt động đối với tôi trong viewDidLoad hoặc viewWillAppear.

Ngoài ra, các giải pháp trên hoạt động tốt.


0

Đối với Monotouch, bạn có thể làm theo cách này:

public override UIInterfaceOrientationMask GetSupportedInterfaceOrientations()
    {
    return UIInterfaceOrientationMask.LandscapeRight;
}

public override UIInterfaceOrientation PreferredInterfaceOrientationForPresentation()
    {
    return UIInterfaceOrientation.LandscapeRight;
}


-1

Chỉ cần truy cập project.plist, sau đó thêm hướng giao diện được hỗ trợ và sau đó chỉ thêm Portrait (nút trang chủ dưới cùng) và Portrait (nút trang chủ trên cùng).

Bạn có thể thêm hoặc bớt định hướng đó theo yêu cầu dự án của bạn.

Cảm ơn


1
về bộ điều khiển chế độ xem cụ thể không dành cho toàn bộ ứng dụng.
Muhammad Rizwan

-2

1) Kiểm tra cài đặt dự án và info.plist của bạn và đảm bảo rằng chỉ những hướng bạn muốn mới được chọn.

2) thêm các phương pháp sau vào bộ điều khiển chế độ xem trên cùng của bạn (bộ điều khiển điều hướng / bộ điều khiển thanh tab)

- (NSUInteger) supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;

}

3) thêm các phương pháp sau vào đại biểu ứng dụng của bạn

- (NSUInteger) supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;

}

- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
    return UIInterfaceOrientationMaskPortrait;

}

-3

Đặt cái này vào tệp .m của từng tệp ViewControllermà bạn không muốn xoay:

- (NSUInteger)supportedInterfaceOrientations
{
    //return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft;
    return UIInterfaceOrientationMaskPortrait;
}

Xem tại đây để biết thêm thông tin.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.