在iPad上,我使用modalPresentationStyle UIModalPresentationPageSheet显示模态视图控制器。此视图控制器使用modalPresentationStyle UIModalPresentationFormSheet呈现另一个模态视图控制器。
因此,用户看到背景视图控制器,页面页面和表单都在彼此之上,因为表单小于页面表。页面表的显示使背景变暗,因此无法与之交互。但是,表格不会使iOS 5上的页面变暗,因此用户仍然可以与下面的页面交互。但是我希望页面页面也变暗,这样用户就可以在他再次与页面页面交互之前关闭模态表单。
在iOS 4上,这是默认行为,但在iOS 5上我找不到实现此目的的方法。你有什么建议吗?
答案 0 :(得分: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>>"
)
解决方案二: 所以在我的动画外观的最终解决方案。 此外,我开始考虑我的第一个解决方案,从技术上来说这可能会让Apple感到厌烦,因为UIDimmingView没有记录,我们“触摸它”。我添加了一个带有背景颜色的UIView alpha我们想要我的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];
}
答案 1 :(得分: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];
}];
}
我不得不调整它,因为快照是静态图像并且不处理旋转,但一般来说它对我来说效果很好。希望它有所帮助。