问题描述
在iPad上,我使用modalPresentationStyle UIModalPresentationPageSheet显示模态视图控制器。此视图控制器使用modalPresentationStyle UIModalPresentationFormSheet呈现另一个模态视图控制器。
On the iPad I display a modal view controller with the modalPresentationStyle UIModalPresentationPageSheet. This view controller presents another modal view controller using the modalPresentationStyle UIModalPresentationFormSheet.
因此,用户在每个视图上看到背景视图控制器,页面表和表单另外,因为表单比页面小。页面表的显示使背景变暗,因此无法与之交互。但是,表单不会使iOS 5上的页面变暗,因此用户仍然可以与下面的页面进行交互。但是我希望页面也变暗,这样用户就可以在他再次与页面交互之前关闭模态表格。
So, the user sees the background view controller, the page sheet and the form sheet all on top of each other, since the form sheet is smaller than the page sheet. The presentation of the page sheet lets the background dim, so that it can't be interacted with. The form sheet, though, does not dim the page sheet on iOS 5, so that the user can still interact with the page sheet underneath. But I want the page sheet dim as well, so that the user hase to close the modal form sheet before he can interact with the page sheet again.
在iOS 4上,这是默认行为,但在iOS 5上我找不到实现此目的的方法。你有什么建议吗?
On iOS 4, this is the default behaviour, but on iOS 5 I couldn't find a way to achieve this. Do you have any suggestions?
推荐答案
我认为这是iOS5中的一个错误。我做了一些实验,从其他模态呈现模态视图控制器,似乎第二个模态永远不会使屏幕下方变暗。我甚至设置了一个测试项目,允许你互相启动无限模态,似乎每个其他模态都不会像预期的那样变暗或阻挡触摸。
I believe this to be a bug in iOS5. I have done some experimenting with presenting modal view controllers from other modals and it seems the second modal NEVER dims the screen underneath. I even setup a test project that allowed you to launch endless modals from each other and it seem every other modal doesn't dim or block touches as expected.
快速的NSLog在UIWindow子视图中向我们显示,在正确添加投影时,dimmingView不是。我正在努力展示自己的调光视图。当我找到方法时会更新这个答案。
A quick NSLog on the UIWindow subviews shows us that while the drop shadow is being added appropriately the dimmingView is not. I'm working on a way to show my own dimming view. Will update this answer when I've found a way.
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没有文档并且我们触摸它而导致拒绝苹果并导致拒绝。我添加了带有背景颜色的UIView alpha我们想要我的viewController。然后我在呈现模态时动画它,当第二个模态的委托被调用时我反转动画。它看起来对我很好。也许一些时间和alpha调整,以使它正确,但它的工作和看起来不错。
Solution Two:So in my final solution for animated look. Also I got to thinking about my first solution and its technically possible this would piss off Apple and cause a rejection since UIDimmingView is undocumented and we "touch it." I add a UIView with a background color the alpha we want to my viewController. then I animated it when I present the modal and I reverse the animation when the delegate of the second modal gets called. It looks pretty good to me. Maybe some timing and alpha tweaks to get it JUST right but its working and looks nice.
- (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];
}];
}
解决方案一:
好吧这样可行,但它并不像我想的那样动画。然而它确实重用了已经存在的东西,所以这可能是一个加号。
Alright so this works but it isn't as animated as I'd like. However it does reuse whats already there so theres probably a plus for that.
- (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中。
Also as a failsafe its probably a good idea to the same stuff in the viewDidDisappear. My done button calls tappedOutside view so I know the gesture and dimmingView are always put right. But if you didn't do it that way you could put it in the 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];
}
这篇关于在模态页面上呈现模态表单的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!