Cocoa touch 如何取消显示为“的模态视图控制器”;表格「;当触摸发生在表单外时?
我有一个视图控制器(带有UIWebView),我以表单样式呈现。 我必须在视图控制器中视图的UIToolbar中放置一个“完成”按钮,才能将其解除。 但是,由于以“表单表”样式呈现,在视图控制器的视图之外留下了大量未使用的空间。。。我在流浪。。 有没有办法检测视野之外的触摸?在那个“灰色”区域?Cocoa touch 如何取消显示为“的模态视图控制器”;表格「;当触摸发生在表单外时?,cocoa-touch,ipad,uiviewcontroller,Cocoa Touch,Ipad,Uiviewcontroller,我有一个视图控制器(带有UIWebView),我以表单样式呈现。 我必须在视图控制器中视图的UIToolbar中放置一个“完成”按钮,才能将其解除。 但是,由于以“表单表”样式呈现,在视图控制器的视图之外留下了大量未使用的空间。。。我在流浪。。 有没有办法检测视野之外的触摸?在那个“灰色”区域? 提前感谢iOS 4.2上的,带有模式表单的基于导航控制器的应用程序的视图层次结构如下:视图将出现:。模态视图出现后,UITransitionView将被包含模态视图层次结构的UIDropShadowVi
提前感谢iOS 4.2上的,带有模式表单的基于导航控制器的应用程序的视图层次结构如下:
视图将出现:
。模态视图出现后,UITransitionView将被包含模态视图层次结构的UIDropShadowView替换
UIWindow
UILayoutContainerView (regular hierarchy)
UIDimmingView
UITransitionView
苹果警告不要依赖内置视图的子视图,因为这些子视图被认为是私有的,在未来的版本中可能会改变。这可能会破坏你的应用程序
方法1我们可以在窗口的最后两个子视图之间插入一个透明视图,并让它通过忽略模态形式来响应触摸事件 此实现检查窗口的视图层次结构是否符合预期,如果不符合预期,则不会执行任何操作 从
view创建并使用DismissingView
将出现在模态视图控制器中:
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:
DismissingView仍然可以添加到视图中的窗口将出现:
,因为UIDropShadowView替换了UITransitionView
同样,如果视图层次结构不符合预期,我们将不执行任何操作
@property (nonatomic, retain) UIView *view;
- (void) addToWindow:(UIWindow*)window modalView:(UIView*)v
{
while (![@"UILayoutContainerView" isEqual:NSStringFromClass([v class])]) {
v = v.superview;
if (!v) {
return;
}
}
self.view = v;
[window addSubview:self];
}
- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event
{
CGPoint p = [self convertPoint:point toView:view];
UIView *v = [view hitTest:p withEvent:event];
return v ? v : [super hitTest:point withEvent:event];
}
我认为正确的答案是,“不要那样做”这里更简单的解决方案:@Cédric该解决方案对于我们的用例来说不够好。添加一个超出视图边界的弹出框,然后单击bam。这个解决方案失败了。