处理具有两种不同视图的视图控制器的最佳方式:纵向和横向

时间:2014-01-30 17:44:14

标签: ios uiview uiviewcontroller device-orientation

根据设备方向,我们的想法是处理两种不同的视图。

基本上,如果我们排除视图,控制器本身只是一段代码。它能够处理两个视图中的任何一个 - 因为IBOutlets在两个IB故事板视图控制器中具有相同的名称,或者因为它对设备方向使用if语句。

我尝试了两种不同的方法,但我仍面临一个问题:我最终得到了两个实际的控制器实例,每个实例都运行相同的代码(因此两次线程和其他代码同时运行)

我想摆脱一个只运行一个实例。

你会建议什么?可能有更好的方法来处理我的用例,不是吗?

我的代码如下:

- (void)loadControllers
{
    self.firstController  = (DashboardViewController*)[[self storyboard] instantiateViewControllerWithIdentifier:@"DashboardPortrait" ];
    self.firstController.isDashboard = NO;

    self.secondController = (DashboardViewController*)[[self storyboard] instantiateViewControllerWithIdentifier:@"DashboardLandscape"];
    self.secondController.isDashboard = YES;
}

- (void)viewDidLoad {
    [super viewDidLoad];

    [self loadControllers];

    DashboardViewController *viewController = self.firstController;
    [self addChildViewController:viewController];

    viewController.view.frame = self.contentView.bounds;

    [self.contentView addSubview:viewController.view];

    self.currentViewController = viewController;
}

- (void)setOrientationPortrait:(BOOL)portrait {
    DashboardViewController *viewController = portrait?self.firstController:self.secondController;


    // Make sure the two view controllers share the same parent.
    [self addChildViewController:viewController];

    // If not same parent, dont transition
    if (viewController.parentViewController!=self.currentViewController.parentViewController) return;

    [self transitionFromViewController:self.currentViewController
                      toViewController:viewController
                              duration:0.0
                               options:UIViewAnimationOptionTransitionNone
                            animations:^{
                                [self.currentViewController.view removeFromSuperview];
                                viewController.view.frame = self.contentView.bounds;
                                [self.contentView addSubview:viewController.view];
                            }
                            completion:^(BOOL finished) {
                                [viewController didMoveToParentViewController:self];
                                [self.currentViewController removeFromParentViewController];
                                self.currentViewController = viewController;


                                // Direct video to the destination, current controller
                                AppDelegate *app = (AppDelegate*)[[UIApplication sharedApplication] delegate];

                                [app faceRecognitionAttachPreview:self.currentViewController.previewView];
                            }
     ];

    self.navigationItem.title = viewController.title;
}

2 个答案:

答案 0 :(得分:1)

根据Apple,如果两者之间存在显着差异,则最佳做法是为两个方向分别设置两个视图控制器。 They say

  

如果要根据设备是纵向还是横向显示不同的数据,则执行此操作的方法是使用两个单独的视图控制器。一个视图控制器应该以主要方向(通常是纵向)管理数据的显示,而另一个视图控制器以交替方向管理数据的显示。使用两个视图控制器比每次方向更改时对视图层次结构进行重大更改更简单,更有效。它允许每个视图控制器专注于一个方向的数据表示,并相应地管理事物。它还消除了使用条件检查当前方向来丢弃视图控制器代码的需要。

答案 1 :(得分:0)

到目前为止,非常好。

在我的背景下,我认为更简单的是最好的解决方案。 然后我放弃了我的两个vc架构,再加上带有嵌入视图的vc,支持一个带有一个视图的vc。

关键是您需要编写代码来处理UI差异 在我的例子中,我还必须改变vc中视图层次结构的方式,以便能够在运行时禁用其中的一些视图。 另外,我不得不放大水平模式的视图,并使用图层的比例变换。不好的一点是,它实际上放大了图形级别。文本不像增加字体大小那样光滑。这是我很快就会做的,以保持最好的质量。

到目前为止,我在设备旋转选择器中编写的代码如下:

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {

    static CGRect actionViewRect = (CGRect){0,0,0,0};

    if (!actionViewRect.size.height) actionViewRect = self.actionView.frame;

    //self.containerView.hidden = YES;

    [UIView transitionWithView:self.view
                      duration:0.3f
                       options:UIViewAnimationOptionTransitionCrossDissolve
                    animations:^{

                        // From portrait to landscape
                        if (UIInterfaceOrientationIsPortrait(fromInterfaceOrientation)) {
                            self.navigationController.navigationBar.hidden = YES;
                            self.tabBarController.tabBar.hidden = YES;

                            self.statusBar.hidden = NO;
                            self.actionView.hidden = YES;
                            self.containerViewTopToSuperView.constant       = self.navigationController.navigationBar.frame.origin.y;
                            self.containerViewBottomToSuperView.constant    = 0;
                            CGRect rect = actionViewRect;
                            rect.origin.y    = actionViewRect.origin.y+actionViewRect.size.height;
                            rect.size.height = 0;
                            self.actionView.frame = rect;

                            // -- location view (bigger)
                            CGFloat
                            s = 1.5;
                            self.locationView.layer.transform = CATransform3DMakeScale(s, s, 1);

                            // -- HUD view (bigger)
                            s = 1.5;
                            self.hudLeft.layer.transform = CATransform3DMakeScale(s, s, 1);

                        }
                        // From landscape to portrait
                        else {
                            self.navigationController.navigationBar.hidden = NO;
                            self.tabBarController.tabBar.hidden = NO;

                            self.locationView.layer.transform = CATransform3DIdentity;


                            self.actionView.hidden = NO;
                            self.actionView.frame = actionViewRect;
                            self.containerViewTopToSuperView.constant       = self.navigationController.navigationBar.frame.origin.y
                                                                            + self.navigationController.navigationBar.frame.size.height;
                            self.containerViewBottomToSuperView.constant    = self.tabBarController.tabBar.frame.size.height;

                            // -- location view (standard)
                            self.hudLeft.layer.transform = CATransform3DIdentity;                        }

                            // -- HUD view (bigger)
                            self.hudLeft.frame           = (CGRect){.origin=(CGPoint){0,0}, .size=self.hudLeft.frame.size};
                    }
                    completion:^(BOOL finished) {
                        // Direct video to the destination, current controller
                        AppDelegate *app = (AppDelegate*)[[UIApplication sharedApplication] delegate];
                        app.previewLayer.orientation = [[UIDevice currentDevice] orientation];

                        //self.containerView.hidden = NO;

                        //[UIView setAnimationsEnabled:YES];

                    }
     ];
}