我有以下子视图链:
UIViewController.view -+
|-> UIView (subclass) -+
| +-> UIToolbar
|
+------------------------> UIWebView
在子类中,我覆盖其-touchesEnded:forEvent:
方法,以便通过CAAnimation
在单击时隐藏和显示UIToolbar
,以及发出导致视图控制器隐藏其导航栏的NSNotification
。
如果我没有将UIWebView
作为子视图添加到视图控制器的视图中,那么这可以正常工作。
如果我然后将UIWebView
添加为视图控制器视图的子视图,则UIToolbar
不会出现,并且我没有获得动画效果。 UIWebView
响应触摸,但子类UIView
不响应。但是,通知会被触发,导航栏会被隐藏。
安排这些子视图的最佳方法是:
- 可以使
UIToolbar
在屏幕上下滑动 -
UIWebView
可见仍然可以接收其典型的触摸事件:放大/缩小和双击以重置缩放级别
编辑 我在这方面取得了一些进展,但我无法区分触摸事件,因此我不应该触发工具栏隐藏/显示方法。 我将视图控制器的视图属性设置为
UIView
子类,并通过[self.view insertSubview:self.webView atIndex:0]
将Web视图插入到-subviews
数组的顶部。
我将以下方法添加到UIView
子类:
- (UIView *) hitTest:(CGPoint) point withEvent:(UIEvent *)event {
UIView *subview = [super hitTest:point withEvent:event];
if (event.type == UIEventTypeTouches) {
[self toggleToolbarView:self];
// get touches
NSSet *touches = [event allTouches];
NSLog(@"subview: %@", subview);
NSLog(@"touches: %@", touches);
// individual touches
for (UITouch *touch in touches) {
switch (touch.phase) {
case UITouchPhaseBegan:
NSLog(@"UITouchPhaseBegan");
break;
case UITouchPhaseMoved:
NSLog(@"UITouchPhaseMoved");
break;
case UITouchPhaseCancelled:
NSLog(@"UITouchPhaseCancelled");
break;
case UITouchPhaseStationary:
NSLog(@"UITouchPhaseStationary");
break;
default:
NSLog(@"other phase...");
break;
}
}
}
return subview;
}
方法-toggleToolbarView:
触发NSTimer
定时的CAAnimation
,其隐藏/显示UIToolbar
。
问题是触摸拖动组合导致-toggleToolbarView:
被触发(以及放大或缩小Web视图)。我想要做的是仅在有触摸事件时触发-toggleToolbarView:
。
当我调用上面的方法-hitTest:withEvent:
时,看起来UIWebView
吸收了触摸。这两个NSLog
报表显示,这是从父UIView
的-hitTest:withEvent:
要么是UIWebView
或UIToolbar
(当它是在屏幕上,触摸)返回UIView*
。 touches
数组为空,因此无法区分触摸事件类型。
还有一件事我会尝试,但我想在这里记录这个尝试,以防其他人有快速建议。感谢您的继续帮助。
编辑二 我在
UIWebView
捏合/缩放和响应双击方面取得了一些进展。我也可以用单击隐藏/显示工具栏。
我没有弄乱UIWebView
实例的私有UIScroller
,而是访问其内部私有UIWebDocumentView
。但放大后,整个网页视图不会正确重绘。
这意味着:例如,如果我的文档包含PDF或SVG矢量插图,则放大会导致内容模糊,就好像构成渲染的PDF或矢量插图内容的图像切片没有被重新渲染一样新的缩放系数。
为了记录这一点,我将:
- 拨打
UIView (subclass)
而不是ViewerOverlayView
-
UIWebView
名为ViewerWebView
UIView
和UIWebView
的子类。
我的ViewerWebView
包含一个新的ivar(使用@property
+ @synthesized
):
UIView *privateWebDocumentView;
(此UIView
实际上是指向UIWebDocumentView
实例的指针,但是为了避免Apple将应用程序标记为拒绝,我将其转换为UIView
,以简单地传递触摸事件。)
ViewerWebView
的实施覆盖了-hitTest:withEvent:
- (UIView *) hitTest:(CGPoint)point withEvent:(UIEvent *)event {
UIView *_subview = [super hitTest:point withEvent:event];
self.privateWebDocumentView = _subview;
return _subview;
}
我的ViewerOverlayView
包含新的ivars(包含@property
+ @synthesized
):
ViewerWebView *webView;
UIView *webDocumentView;
在叠加视图的实现中,我重写了-touchesBegan:withEvent:
,-touchesMoved:withEvent:
和-touchesEnded:withEvent:
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
self.touchHasMoved = NO;
if (self.webView) {
UITouch *touch = [touches anyObject];
CGPoint touchPoint = [touch locationInView:self];
self.webDocumentView = [self.webView hitTest:touchPoint withEvent:event];
}
[super touchesBegan:touches withEvent:event];
[self.webDocumentView touchesBegan:touches withEvent:event];
}
-
(void) touchesMoved:(NSSet )touches withEvent:(UIEvent )event {
self.touchHasMoved = YES;
if (self.webView) {
UITouch *touch = [touches anyObject];
CGPoint touchPoint = [touch locationInView:self];
self.webDocumentView = [self.webView hitTest:touchPoint withEvent:event];
}
[super touchesMoved:touches withEvent:event];
[self.webDocumentView touchesMoved:touches withEvent:event];
}
-
(void) touchesEnded:(NSSet )touches withEvent:(UIEvent )event {
if(!self.touchHasMoved)
[self toggleToolbarView:self];
if (self.webView) {
UITouch *touch = [touches anyObject];
CGPoint touchPoint = [touch locationInView:self];
self.webDocumentView = [self.webView hitTest:touchPoint withEvent:event];
}
[super touchesEnded:touches withEvent:event];
[self.webDocumentView touchesEnded:touches withEvent:event];
}
在视图控制器中,我执行以下操作:
- 实例化
ViewerOverlayView
并将其添加为视图控制器的view
属性的子视图 - 实例化视图控制器的
ViewerWebView
实例并将其插入子视图数组的底部 - 将
ViewerOverlayView
网络视图属性设置为视图控制器的网络视图
ViewerOverlayView
正确地将缩放/拉伸/双击触摸事件传递给ViewerWebView
实例的私有UIWebDocumentView
实例。然后UIWebDocumentView
调整大小。
但是,内容不会使用新比例重绘。因此,基于矢量的内容(例如PDF,SVG)在放大时看起来很模糊。
这是视图看起来没有缩放,漂亮和锐利的样子:


ViewerWebView
及其内部UIWebDocumentView
实例上尝试了-setNeedsDisplay
。两种方法调用都不起作用。
尽管我想避免使用私有方法,但由于我希望最终获得此应用程序的批准,我还尝试了访问私有UIWebDocumentView
方法-_webCoreNeedsDisplay
的this suggestion:
[(UIWebDocumentView *)self.webDocumentView _webCoreNeedsDisplay];
此方法导致应用程序从unrecognized selector
异常中崩溃。也许Apple已将此方法的名称从SDK 3.0更改为3.1.2。
除非有办法让Web视图重绘其内容,否则我想我必须废弃透明覆盖视图并只绘制Web视图,以使Web视图正常工作。太糟糕了!
如果有人有关于重绘后缩放的想法,请随时添加答案。
再次感谢大家的投入。顺便说一句,我没有取消这个问题的赏金 - 我不知道为什么它不会自动被授予这个帖子的第一个答案,因为我原本期望从以前的经验中发生。
编辑III 我发现这个网页显示了how to subclass the application window,以便观察点击并将这些点击转发给视图控制器。 没有必要在整个应用程序中的任何地方实现其委托,只有在我想观察
UIWebView
上的点击时才这样,所以这对于文档查看器来说可能非常有效。
到目前为止,我可以观察点击,隐藏和显示工具栏,UIWebView
的行为类似于Web视图。我可以放大和缩小Web视图,并正确地重新呈现文档。
虽然学习如何以更通用的方式管理水龙头会很好,但这看起来是一个非常好的解决方案。
没有找到相关结果
4 个回复
lillo
赞同来自:
我正在阅读你的问题的方式,你想拦截事件来触发一些动作(动画工具栏,发布通知),同时允许事件也到达其自然目的地。 如果我试图这样做,我会将
通过发回您想要接收事件的视图(UIToolbar或UIWebView),视图可以侧面成为事件处理的一部分,同时您仍有机会触发所需的操作。 一个例子可能是:UIToolbar
直接作为UIViewController.view
的子视图。UIWebView
也是直接子视图。UIViewController.view
应该是UIView
的子类,它需要覆盖pnon
赞同来自:
如果您首先将UIView子类添加到视图控制器的视图中,然后按照您的描述添加UIWebView,UIWebView将完全覆盖UIView子类(假设两个视图完全重叠,如您在问题注释中所提到的那样)。 听起来你不想要那个 - 你想要Web视图上方的子类。您需要以相反的顺序将它们添加到视图控制器的视图中(添加Web视图,然后添加自定义UIView)或调用:
有了这个,让我们谈谈如何拦截触摸事件。我将建议一种不同的方法,让我做一些类似的事情。 Here's the question and answer I created for it - 随时可以查看有关此技术的更多详细信息。 我们的想法是您将UIApplication子类化并覆盖-sendEvent:方法。你会看起来像这样,我想: 我不认为这会让你100%在那里,但希望这是一个开始。特别是,您可能想要使用if条件来检查您正在处理的UITouches的属性。我不确定我是否包括正确的支票,或者他们是否能抓住你正在寻找的确切条件。 祝你好运!onam
赞同来自:
好的,这个怎么样:
UIView
子类中,添加指向UIWebView
的指针UIView
子类,BOOL hasMoved;
UIView
子类中,覆盖这样的触摸方法: 然后将自定义视图放在Web视图的顶部。看起来太简单了,可能是 - 可能需要一些魔法来正确处理多个触摸,你可能需要在touchesBegan:
方法中使用NSTimer
作为延迟来处理双击情况,但我认为一般的想法是声音...也许?dsit
赞同来自:
取2:与上面相同,但重写方法如下:
这有点......有点儿。这允许您拖动Web视图。但它没有正确处理其他触摸事件(链接,捏,任何东西)。所以。可能不是很有用,但它对我来说是进步!