使用 uinavigationcontroller 作为 uitabbarcontroller 的选项卡时,如何仅旋转某些视图

发布于 2024-08-31 02:17:26 字数 5412 浏览 2 评论 0原文

这是一个我不知道如何工作的流程。 (当我声明(工作)时,这意味着在当前状态下,该视图的方向规则正常工作)

第一个视图:UINavigationController 堆栈上的 TableView,它是 UITabBarController 的一个选项卡。

TableView 只允许是纵向的。 (在职的) 当您旋转 TableView 进行横向显示时,模式会出现一个自定义 UIView,就像一个封面流(我稍后将解释那里的问题)。

在 tableview 上进行的选择会将 UIScrollview 推送到堆栈上。

UIScrollView 允许所有方向。 (工作)

当 UIScrollView 处于横向模式并且用户回击时,他们将被带到类似于 coverflow 且仅允许横向的自定义 UIView。

问题就在这里。因为 UIScrollView 允许完全旋转,所以它也允许 TableView 旋转到横向。

我有一个附加到通知“UIDeviceOrientationDidChangeNotification”的方法,该方法检查自定义视图是否是当前控制器,如果是,以及用户是否已旋转回纵向,我需要弹出自定义视图并显示表格视图。

表格视图必须旋转回纵向,只要用户看不到它就真的没问题。当我创建自定义动画时,它的效果非常好,除了一些奇怪的隐形黑框,它似乎在我将自定义视图淡出到桌面视图之前随设备旋转。

此外,为了确保我的桌面视图将旋转到纵向,我必须允许自定义视图支持所有方向,因为系统会查看当前视图(在我的代码中)以确定是否允许该应用程序旋转到某个方向。因此,我提出的许多解决方案将在表格视图返回焦点时显示自定义视图旋转为纵向。

我的另一个问题非常相似。如果您正在查看表格视图并旋转,则会显示自定义视图的模态视图。当您在此视图上进行选择时,它会将 UIScrollview 推入堆栈,但由于 Tableview 仅支持纵向,因此当设备处于横向模式时,UIScrollview 会以纵向显示。

我怎样才能克服这些可怕的障碍?

这是我当前的尝试:

当涉及到使用 UITabBarController 时,系统实际上只关心 tabbarcontroller 关于旋转的说明。

目前,每当视图加载时,它都会报告其支持的方向。

TabBarController.m

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
switch (self.supportedOrientation) {
    case SupportPortraitOrientation:
        [[UIApplication sharedApplication] setStatusBarHidden:NO animated:YES]; 
        return (interfaceOrientation == UIInterfaceOrientationPortrait);
        break;
    case SupportPortraitUpsideDownOrientation:
        [[UIApplication sharedApplication] setStatusBarHidden:NO animated:YES]; 
        return (interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown);
        break;
    case SupportPortraitAllOrientation:
        [[UIApplication sharedApplication] setStatusBarHidden:NO animated:YES]; 
        return (interfaceOrientation == UIInterfaceOrientationPortrait || interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown);
        break;
    case SupportLandscapeLeftOrientation:
        [[UIApplication sharedApplication] setStatusBarHidden:YES animated:YES]; 
        return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft);
        break;
    case SupportLandscapeRightOrienation:
        [[UIApplication sharedApplication] setStatusBarHidden:YES animated:YES];            
        return (interfaceOrientation == UIInterfaceOrientationLandscapeRight);
        break;
    case SupportLandscapeAllOrientation:
        [[UIApplication sharedApplication] setStatusBarHidden:YES animated:YES]; 
        return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft || interfaceOrientation == UIInterfaceOrientationLandscapeRight);
        break;
    case SupportAllOrientation:
        if (interfaceOrientation == UIInterfaceOrientationLandscapeLeft || interfaceOrientation == UIInterfaceOrientationLandscapeRight) {
            [[UIApplication sharedApplication] setStatusBarHidden:YES animated:YES]; 
        }else {
            //[[UIApplication sharedApplication] setStatusBarHidden:NO animated:YES]; 
        }
        return YES;
        break;
    default:
        return (interfaceOrientation == UIInterfaceOrientationPortrait);
        break;
    }

}

此代码块是我的 UINavigationController 的一部分,位于响应 UIDeviceOrientationDidChangeNotification 通知的方法中。它负责弹出自定义视图并显示表格视图。有两个不同的版本最初用于两个不同版本的 SDK,但两者都非常接近解决方案。

第一个在 3.0 上不受支持的原因是由于某种原因,您无法先显示视图,然后再将其显示为模态视图。不确定这是一个错误还是一个功能。

第二种解决方案效果很好,只是我看到一个外盒围绕 iPhone 旋转。

if ([[self topViewController] isKindOfClass:FlowViewController.class]) {
    NSString *iphoneVersion = [[UIDevice currentDevice] systemVersion];
    double version = [iphoneVersion doubleValue];
    if(version > 3.0){ //1st solution
        //if the delivered app is not built with the 3.1 SDK I don't think this will happen anyway
        //we need to test this
        [self presentModalViewController:self.flowViewController animated:NO];
        //[self toInterfaceOrientation:UIDeviceOrientationPortrait animated:NO];
        [self popViewControllerAnimated:NO];
        [self setNavigationBarHidden:NO animated:NO];
        [self dismissModalViewControllerAnimated:YES];
    }else{ //2nd solution
        DLog(@"3.0!!");
        //[self toInterfaceOrientation:UIDeviceOrientationPortrait animated:NO];
        CATransition *transition = [CATransition animation];
        transition.duration = 0.50;
        transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
        transition.type = kCATransitionPush;
        transition.subtype = kCATransitionFade;

        CATransition *tabBarControllerLayer = [CATransition animation];
        tabBarControllerLayer.duration = 0.50;
        tabBarControllerLayer.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
        tabBarControllerLayer.type = kCATransitionPush;
        tabBarControllerLayer.subtype = kCATransitionFade;

        [self.tabBarController.view.layer addAnimation:transition forKey:kCATransition];
        [self.view.layer addAnimation:transition forKey:kCATransition];
        [self popViewControllerAnimated:NO];
        [self setNavigationBarHidden:NO animated:NO];

    }
    [self performSelector:@selector(resetFlow) withObject:nil afterDelay:0.75];

}

我几乎确信除了手动旋转之外没有其他解决方案,这会扰乱键盘旋转。

任何建议将不胜感激!

谢谢。

Here is a flow that I can not figure out how to work. ( when I state (working) it means that in that current state the rules for orientation for that view are working correctly)

First View: TableView on the stack of a UINavigationController that is a tab of UITabBarController.

TableView is only allowed to be portrait. (working)
When you rotate the TableView to landscape a modal comes up with a custom UIView that is like a coverflow (which i'll explain the problem there in a moment).

A Selection made on tableview pushes a UIScrollview on to the stack.

UIScrollView is allowed all orientations. (working)

When UIScrollView is in landscape mode and the user hits back they are taken to the custom UIView that is like the coverflow and only allows landscape.

The problem is here. Because the UIScrollView allows full rotation it permitted the TableView to rotate as well to landscape.

I have a method attached to a notification "UIDeviceOrientationDidChangeNotification" that checks to see if the custom view is the current controller and if it is and if the user has rotated back to portrait I need to pop the custom view and show the table view.

The table view has to rotate back to portrait, which really is okay as long as the user doesn't see it. When I create custom animations it works pretty good except for some odd invisible black box that seems to rotate with the device right before I fade out the customview to the tableview.

Further inorder to ensure that my tableview will rotate to portrait I have to allow the customview to support all orientations because the system looks to the current view (in my code) as to whether or not that app is allowed to rotate to a certain orientation. Because of this I many proposed solutions will show the customview rotating to portrait as the table view comes back to focus.

My other problem is very similar. If you are viewing the tableview and rotate the modalview of the customview is presented. When you make a selection on this view it pushes the UIScrollview onto the stack, but because the Tableview only supports portrait the UIScrollview comes in in portrait while the device is in landscape mode.

How can I overcome these awful blocks?

This is my current attempt:

When it comes to working with UITabBarController the system really only cares what the tabbarcontroller has to say about rotation.

Currently whenever a view loads it reports it supported orientations.

TabBarController.m

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
switch (self.supportedOrientation) {
    case SupportPortraitOrientation:
        [[UIApplication sharedApplication] setStatusBarHidden:NO animated:YES]; 
        return (interfaceOrientation == UIInterfaceOrientationPortrait);
        break;
    case SupportPortraitUpsideDownOrientation:
        [[UIApplication sharedApplication] setStatusBarHidden:NO animated:YES]; 
        return (interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown);
        break;
    case SupportPortraitAllOrientation:
        [[UIApplication sharedApplication] setStatusBarHidden:NO animated:YES]; 
        return (interfaceOrientation == UIInterfaceOrientationPortrait || interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown);
        break;
    case SupportLandscapeLeftOrientation:
        [[UIApplication sharedApplication] setStatusBarHidden:YES animated:YES]; 
        return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft);
        break;
    case SupportLandscapeRightOrienation:
        [[UIApplication sharedApplication] setStatusBarHidden:YES animated:YES];            
        return (interfaceOrientation == UIInterfaceOrientationLandscapeRight);
        break;
    case SupportLandscapeAllOrientation:
        [[UIApplication sharedApplication] setStatusBarHidden:YES animated:YES]; 
        return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft || interfaceOrientation == UIInterfaceOrientationLandscapeRight);
        break;
    case SupportAllOrientation:
        if (interfaceOrientation == UIInterfaceOrientationLandscapeLeft || interfaceOrientation == UIInterfaceOrientationLandscapeRight) {
            [[UIApplication sharedApplication] setStatusBarHidden:YES animated:YES]; 
        }else {
            //[[UIApplication sharedApplication] setStatusBarHidden:NO animated:YES]; 
        }
        return YES;
        break;
    default:
        return (interfaceOrientation == UIInterfaceOrientationPortrait);
        break;
    }

}

This block of code is part of my UINavigationController and is in a method that responds to the UIDeviceOrientationDidChangeNotification Notification. It is responsible for poping the customview and showing the tableview. There are two different versions in place that originally were for two different versions of the SDK but both are pretty close to solutions.

The reason the first is not supported on 3.0 is for some reason you can't have a view showing and then showen as a modal view. Not sure if that is a bug or a feature.

The second solution works pretty good except that I see an outer box rotating around the iphone.

if ([[self topViewController] isKindOfClass:FlowViewController.class]) {
    NSString *iphoneVersion = [[UIDevice currentDevice] systemVersion];
    double version = [iphoneVersion doubleValue];
    if(version > 3.0){ //1st solution
        //if the delivered app is not built with the 3.1 SDK I don't think this will happen anyway
        //we need to test this
        [self presentModalViewController:self.flowViewController animated:NO];
        //[self toInterfaceOrientation:UIDeviceOrientationPortrait animated:NO];
        [self popViewControllerAnimated:NO];
        [self setNavigationBarHidden:NO animated:NO];
        [self dismissModalViewControllerAnimated:YES];
    }else{ //2nd solution
        DLog(@"3.0!!");
        //[self toInterfaceOrientation:UIDeviceOrientationPortrait animated:NO];
        CATransition *transition = [CATransition animation];
        transition.duration = 0.50;
        transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
        transition.type = kCATransitionPush;
        transition.subtype = kCATransitionFade;

        CATransition *tabBarControllerLayer = [CATransition animation];
        tabBarControllerLayer.duration = 0.50;
        tabBarControllerLayer.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
        tabBarControllerLayer.type = kCATransitionPush;
        tabBarControllerLayer.subtype = kCATransitionFade;

        [self.tabBarController.view.layer addAnimation:transition forKey:kCATransition];
        [self.view.layer addAnimation:transition forKey:kCATransition];
        [self popViewControllerAnimated:NO];
        [self setNavigationBarHidden:NO animated:NO];

    }
    [self performSelector:@selector(resetFlow) withObject:nil afterDelay:0.75];

}

I'm near convinced there is no solution except for manual rotation which messes up the keyboard rotation.

Any advice would be appreciated!

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

后知后觉 2024-09-07 02:17:26

如果您在选项卡栏控制器中有一个导航控制器,并且只想允许某些视图旋转,我有解决方案。它可能并不适合所有人,也可能不是最干净的代码,但到目前为止,它是唯一的解决方案。

另外,此方法假设您在离开第一个视图时不希望看到选项卡栏,尽管您可以使用 popOverControllers 实现我的解决方案,但我不确定。

创建标签栏控制器
创建导航控制器
创建第二个导航控制器,该控制器不会位于选项卡栏控制器上
将第一个导航控制器放入标签栏控制器中
配置将 ViewController 推送到第一个的方法:

截取当前屏幕的屏幕截图。
将屏幕截图放入 UIViewController 中
将 UIViewController 推到第二个导航控制器上
以模态方式呈现第二个导航控制器
大约 0.15 秒的延迟后,将所需的视图控制器推送到第二个导航控制器的导航堆栈上。

现在,您当前的控制器已脱离 tabBarcontroller,并且它的旋转(因为此导航控制器以模态方式呈现)独立于 tabBarController!

您需要做一些工作才能返回到第一个视图,但这并不难。

这是一个详细的解决方案,我将尝试在一段时间内编写代码。他们的答案更多,但这应该足以让您开始,如果您需要帮助,请告诉我。

If you have a navigation controller in a tab bar controller and you only want to allow some views to rotate I have the solution. It may not work for everyone and it may not be the cleanest code, but so far it is the only solution.

Also, this method assumes that you do not want to see the tab bar when you are off of the first view, although you could possible implement my solution with popOverControllers but I am unsure.

Create the tabbar controller
Create the navigation controller
Create a second navigation controller that will not be on tabbar controller
put the first navigation controller in the tabbar controller
configure methods that will pushViewController to first:

take a screenshot of the current screen.
put that screenshot into a UIViewController
push that UIViewController onto the second navigation controller
present the second navigation controller modally
after a delay of about .15 seconds push the wanted viewcontroller onto the navigation stack of the second navigation controller.

Now your current controller is off of the tabBarcontroller and it's rotation (because this navigation controller is presented modally) is independent of the tabBarController!

You'll have to do some work to move back to your first view, but it isn't that hard.

This is a detailed solution and I will try to get code up some time. Their is more to this answer but this should be enough to get you started, if you need help just let me know.

゛时过境迁 2024-09-07 02:17:26

嗨,您可以尝试所有这些:

我在每个视图中使用此行,以便您可以在任何视图中更改首选方向:

- (BOOL)shouldAutorotate
{
    return YES;
}

- (NSUInteger)supportedInterfaceOrientations
{
    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
        return UIInterfaceOrientationMaskPortrait;
    } else {
        return UIInterfaceOrientationMaskAll;
    }
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
    return UIInterfaceOrientationPortrait;
}

然后您必须子类化 UINavigationController 和 UITabBarController,所以这里是代码:

//cCustomNavigationController.h file

#import <UIKit/UIKit.h>

@interface cCustomNavigationController : UINavigationController <UINavigationControllerDelegate>

@end

//cCustomNavigationController.m file

#import "cCustomNavigationController.h"

@interface cCustomNavigationController ()

@end

@implementation cCustomNavigationController 

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

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

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

@end

//cCustomTabController.h file

#import <UIKit/UIKit.h>

@interface cCustomTabController : UITabBarController <UITabBarControllerDelegate>

@end

//cCustomTabController.m file

#import "cCustomTabController.h"

@interface cCustomTabController  ()

@end

@implementation cCustomTabController

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

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

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

@end

现在您只需创建 TabBarControler或者您的 NavigationController 在您需要的地方使用此类,即

//For the UINavigationController
UINavigationController *navigationController = [[cCustomNavigationController alloc] init];

//For the UITabBarController
UITabBarController *tabController = [[cCustomTabController alloc] init];

现在有了这个您可以按照您想要的方式控制所有视图的旋转,我正在使用它并且它工作正常。

我希望这对您有帮助,但我不确定这是否正是您所需要的。

快乐编码。

hi you can try all this:

i'm using this lines in every view so you can change the prefered orientation in any view:

- (BOOL)shouldAutorotate
{
    return YES;
}

- (NSUInteger)supportedInterfaceOrientations
{
    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
        return UIInterfaceOrientationMaskPortrait;
    } else {
        return UIInterfaceOrientationMaskAll;
    }
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
    return UIInterfaceOrientationPortrait;
}

Then you have to subclass UINavigationController and UITabBarController, so here is the code:

//cCustomNavigationController.h file

#import <UIKit/UIKit.h>

@interface cCustomNavigationController : UINavigationController <UINavigationControllerDelegate>

@end

//cCustomNavigationController.m file

#import "cCustomNavigationController.h"

@interface cCustomNavigationController ()

@end

@implementation cCustomNavigationController 

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

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

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

@end

//cCustomTabController.h file

#import <UIKit/UIKit.h>

@interface cCustomTabController : UITabBarController <UITabBarControllerDelegate>

@end

//cCustomTabController.m file

#import "cCustomTabController.h"

@interface cCustomTabController  ()

@end

@implementation cCustomTabController

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

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

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

@end

now you just have to create your TabBarControler or your NavigationController using this classes where ever you need it i.e.

//For the UINavigationController
UINavigationController *navigationController = [[cCustomNavigationController alloc] init];

//For the UITabBarController
UITabBarController *tabController = [[cCustomTabController alloc] init];

Now with this you can control the rotation of all your views in the way you want, i'm using it and it works fine.

I hope this help you, but i'm not sure if this is exaclty what you need.

Happy coding.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文