2012-04-11 91 views
4

在iPad上,我使用modalPresentationStyle UIModalPresentationPageSheet显示模态视图控制器。此视图控制器使用modalPresentationStyle UIModalPresentationFormSheet显示另一个模式视图控制器。在模态页面上显示模态表单

因此,由于表单小于页面表单,所以用户看到背景视图控制器,页面表单和表单表单全部在彼此之上。页面的表示让背景变暗,以至于无法与之互动。但是,表单不会在iOS 5中调暗页面表,以便用户仍然可以与下面的页面页进行交互。但是我也希望页面变暗,以便用户在能够再次与页面交互之前关闭模式表单。

在iOS 4上,这是默认行为,但在iOS 5上我找不到实现此目的的方法。你有什么建议吗?

+0

我在iOS 5中注意到了这一点,并且在iOS 6中看到了同样的问题。 – arlomedia 2012-10-19 23:43:57

+0

我刚刚提交了这个错误报告12540692. – arlomedia 2012-10-20 00:37:21

回答

2

我相信这是iOS5中的一个错误。我已经做了一些试验,展示其他模态的模态视图控制器,看起来第二个模态从不会调暗下面的屏幕。我甚至设置了一个测试项目,允许你从对方发起无尽的模态,并且看起来每个其他模态都不会像预期的那样调暗或阻挡触摸。

UIWindow子视图的快速NSLog向​​我们显示,当正在添加阴影时,dimmingView不适用。我正在努力展示我自己的调光视图。当我找到方法时会更新这个答案。

Window Subviews: (
    "<UILayoutContainerView: 0xf63e3c0; frame = (0 0; 768 1024); transform = [0, 1, -1, 0, 0, 0]; autoresize = W+H; layer = <CALayer: 0xf645640>>", 
    "<UIDimmingView: 0xf683990; frame = (0 0; 768 1024); opaque = NO; layer = <CALayer: 0xf6836d0>>", 
    "<UIDropShadowView: 0xf683130; frame = (64 64; 640 896); transform = [0, 1, -1, 0, 0, 0]; autoresize = W+H; layer = <CALayer: 0xf6831c0>>", 
    "<UIDropShadowView: 0x292110; frame = (74 242; 620 540); transform = [0, 1, -1, 0, 0, 0]; autoresize = LM+RM+TM+BM; layer = <CALayer: 0x292150>>" 
) 

解决方法二: 所以在我的动画看最终的解决方案。 此外,我不得不考虑我的第一个解决方案,它的技术可能性会使苹果产生排斥并导致拒绝,因为UID预览没有记录,我们“接触它”。我添加了一个背景颜色的UIView我们想要我的viewController的alpha。然后当我呈现模态时动画,并在第二个模态的代表被调用时反转动画。它对我来说很不错。也许一些时机和alpha调整,以得到它只是正确的,但其工作,并看起来不错。

- (void)viewDidLoad 
{ 
    dim = [[UIView alloc] init]; 
    [dim setBackgroundColor:[UIColor colorWithWhite:0.0 alpha:0.35]]; 
    [dim setAlpha:0.0]; 
    [dim setUserInteractionEnabled:NO]; 
    [self.view addSubview:dim]; 
} 

- (void)presentModal 
{ 
    [self.view bringSubviewToFront:dim]; 
    [dim setFrame:self.view.frame]; 
    [UIView animateWithDuration:0.25 animations:^{ 
     [dim setAlpha:1.0]; 
    }]; 
} 

- (void)modalDelegateFinished 
{ 
    [UIView animateWithDuration:0.25 animations:^{ 
     [dim setAlpha:0.0]; 
    }]; 
} 

解决方法一:

好吧,所以这个工作,但它并不像动画片,我想。然而,它确实重用了已有的东西,所以可能还有一个好处。

- (void)viewDidAppear:(BOOL)animated 
{ 
    // Add a gesture to dismiss the view if tapped outside. 
    UIGesture *gesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tappedOutsideView:)]; 
    [gesture setNumberOfTapsRequired:1]; 
    [gesture setCancelsTouchesInView:NO]; 
    [self.view.window addGestureRecognizer:gesture]; 

    // Move the dimmingview to just below the dropshadow. 
    UIView *dim = [self.view.window.subviews objectAtIndex:1]; 
    [self.view.window insertSubview:dim atIndex:2]; 
} 

- (void)tappedOutsideView:(UITapGestureRecognizer *)sender 
{ 
    if (sender.state == UIGestureRecognizerStateEnded) { 
     CGPoint location = [sender locationInView:nil]; 

     if (![self.view pointInside:[self.view convertPoint:location fromView:self.view.window] withEvent:nil]) { 
      // remove the gesture on the window 
      [self.view.window removeGestureRecognizer:sender]; 

      // Move the dimmingview back where it belongs 
      UIView *dim = [self.view.window.subviews objectAtIndex:2]; 
      [self.view.window insertSubview:dim atIndex:1]; 
     } 
    } 
} 

此外作为一个失败保险,它可能是一个好主意,在viewDidDisappear相同的东西。我完成的按钮调用tappedOutside视图,所以我知道手势和dimmingView总是正确的。但如果你没有这样做,你可以把它放在viewDidDisappear中。

- (void)viewDidDisappear:(BOOL)animated 
{ 
    // remove the gesture on the window 
    for (UIGestureRecognizer *gesture in self.view.window.gestureRecognizers) { 
     [self.view.window removeGestureRecognizer:gesture]; 
    } 

    // Move the dimmingview back where it belongs 
    UIView *dim = [self.view.window.subviews objectAtIndex:2]; 
    [self.view.window insertSubview:dim atIndex:1]; 
} 
+0

这是我的expraience。现在,我只是不在页面顶部展示表单并在我的应用中随处使用页面表。 – Tom 2012-04-23 12:51:42

+0

我已经设置了窗口手势,因此在模态之外点击总是会导致它解散。所以,因为触摸不能通过我的手势,他们可以通过背景模态。 然而,从视觉上来说,它会很好地变暗。我可能在一个系统上工作,除了模态之外,将窗口中的所有内容调暗。 – 2012-04-23 14:51:05

+0

更新了我的答案。我找到了两个解决方案。比另一个更加动画和安全。 :) – 2012-04-23 15:59:32

0

它看起来像一个iOS的错误。仍然在iOS7中。

以下是我所做的工作(iOS7测试)。有趣的是,在模态上呈现模态不会暗淡主持人,但会在这些模式之上呈现第三种模态。

知道这一点之后,我们可以在呈现实际表单模式之前​​呈现一个虚拟物体。这涉及最少的代码,并且在技术上符合一般的iOS设计模式。所以未来爆炸的风险应该是最小的。

首先呈现形式片:

- (void)presentFormSheetModalOverThePageSheetModal 
{ 
    //get the controller I'm trying to present and stick it in a nav controller - as usual 
    UIViewController *myModalController = [UIViewController new]; 
    UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:myModalController]; 
    navController.modalPresentationStyle = UIModalPresentationFormSheet; 

    //create an intermediate controller that will be presented first 
    UIViewController *intermediateController = [UIViewController new]; 
    intermediateController.modalPresentationStyle = UIModalPresentationCurrentContext; 
    intermediateController.view.backgroundColor = self.view.backgroundColor; 

    //create a snapshot of self (presenting controller) 
    UIView *navBar = [self.navigationController.navigationBar snapshotViewAfterScreenUpdates:YES]; 
    UIView *mainView = [self.view snapshotViewAfterScreenUpdates:YES]; 
    mainView.center = CGPointMake(mainView.center.x, mainView.center.y + navBar.frame.size.height); 
    [intermediateController.view addSubview:navBar]; 
    [intermediateController.view addSubview:mainView]; 

    //two step presentation 
    [self presentViewController:intermediateController animated:NO completion:^{ 
     [intermediateController presentViewController:navController animated:YES completion:nil]; 
    }]; 
} 

然后,当它的时间以关闭(从所呈现的模态):

- (void)dismissMySelf 
{ 
    //again - two step process to dismiss the this controller and the intermediate controller 
    UIViewController *originalPresenter = self.presentingViewController.presentingViewController; 
    [self.presentingViewController dismissViewControllerAnimated:YES completion:^{ 
     [originalPresenter dismissViewControllerAnimated:NO completion:nil]; 
    }]; 
} 

我不得不调整它,因为在快照是一个静态图像并没有处理旋转,但总的来说,它对我很好。希望能帮助到你。