在模态页面表上呈现模态表单表

2024-03-21

在 iPad 上,我使用 modalPresentationStyle UIModalPresentationPageSheet 显示模式视图控制器。该视图控制器使用 modalPresentationStyle UIModalPresentationFormSheet 呈现另一个模式视图控制器。

因此,用户会看到背景视图控制器、页面表和表单都在彼此之上,因为表单表比页面表小。页面的呈现方式让背景变暗,从而无法与之交互。不过,在 iOS 5 上,表单不会使页面表变暗,因此用户仍然可以与下面的页面表进行交互。但我也希望页面变暗,以便用户必须先关闭模式表单,然后才能再次与页面交互。

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


我认为这是 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>>"
)

解决方案二:所以在我的动画外观的最终解决方案中。另外,我还开始考虑我的第一个解决方案,从技术上讲,这可能会激怒苹果并导致拒绝,因为 UIDimmingView 没有文档记录,而我们“接触了它”。我将一个带有我们想要的 alpha 背景颜色的 UIView 添加到我的 viewController 中。然后我在呈现模态时对其进行动画处理,并在调用第二个模态的委托时反转动画。对我来说看起来不错。也许需要进行一些时间和 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];
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在模态页面表上呈现模态表单表 的相关文章

随机推荐