我有一个以表单样式呈现的视图控制器(带有UIWebView)。 我必须在视图控制器的视图的UIToolbar中放置一个“完成”按钮才能将其解除。 但是,由于以“表单”样式呈现它会在视图控制器的视图之外留下大量未使用的空间......我在游荡... 有没有办法检测视图外的触摸?在那个“变灰”的地方? 提前致谢
答案 0 :(得分:18)
在iOS 4.2上,基于导航控制器的应用程序的视图层次结构与模态表单在viewWillAppear:
期间如下所示。一旦出现模态视图,UITransitionView就被包含模态视图层次结构的UIDropShadowView所取代。
UIWindow
UILayoutContainerView (regular hierarchy)
UIDimmingView
UITransitionView
Apple警告不要依赖内置视图的子视图,因为这些视图被认为是私有的,并且可能在将来的版本中发生变化。这可能会破坏您的应用。
方法1
我们可以在窗口的最后两个子视图之间插入透明视图,并通过关闭模态窗体来响应触摸事件。
此实现检查窗口的视图层次结构是否符合预期,否则将默默地执行任何操作。
在模态视图控制器中从DismissingView
创建并使用viewWillAppear:
。
DismissingView *dismiss = [[DismissingView alloc] initWithFrame:window.frame
selector:@selector(dismissView:) target:self];
[dismiss addToWindow:window];
[dismiss release];
并实施。
@interface DismissingView : UIView {
}
@property (nonatomic, retain) id target;
@property (nonatomic) SEL selector;
- (id) initWithFrame:(CGRect)frame target:(id)target selector:(SEL)selector;
@end
@implementation DismissingView
@synthesize target;
@synthesize selector;
- (id) initWithFrame:(CGRect)frame target:(id)target selector:(SEL)selector
{
self = [super initWithFrame:frame];
self.opaque = NO;
self.backgroundColor = [UIColor clearColor];
self.selector = selector;
self.target = target;
return self;
}
- (void) addToWindow:(UIWindow*)window
{
NSUInteger count = window.subviews.count;
id v = [window.subviews objectAtIndex:count - 1];
if (![@"UITransitionView" isEqual:NSStringFromClass([v class])]) return;
v = [window.subviews objectAtIndex:count - 2];
if (![@"UIDimmingView" isEqual:NSStringFromClass([v class])]) return;
UIView *front = [window.subviews lastObject];
[window addSubview:self];
[window bringSubviewToFront:front];
}
- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
{
[self removeFromSuperview];
[target performSelector:selector withObject:self];
}
@end
方法2
第一种方法是首选方法,因为这种方法对模态形式的每个触摸事件都有额外的逻辑。
将透明视图添加为窗口的前视图。模态视图框架内的触摸事件将传递给它,框架外的触摸事件将忽略模态窗体。
在它出现之前,模态视图层次结构如下所示。当它出现时,UIDropShadowView将替换窗口子视图中的UITransitionView。 UILayoutContainerView
UIDropShadowView
UIImageView
UILayoutContainerView
UINavigationTransitionView
UIViewControllerWrapperView
UIView (the modal view)
UINavigationBar
实施与以前大致相同,新属性addToWindow:
替换为addToWindow:modalView:
。
由于UIDropShadowView取代了UITransitionView,因此仍然可以将{[1}}中的DismissingView添加到窗口中。
如果视图层次结构不符合预期,我们也会默默地做任何事情。
viewWillAppear:
答案 1 :(得分:-4)
我认为正确的答案是,"不要这样做"