我有以下 subview 链:
UIViewController.view -+
|-> UIView (subclass) -+
| +-> UIToolbar
|
+------------------------> UIWebView
在子类中,我覆盖了它的
-touchesEnded:forEvent:
方法来隐藏和显示 UIToolbar
只需轻轻一按,即可通过 CAAnimation
,以及发出 NSNotification
这会导致 View Controller 隐藏其导航栏。如果我不添加
UIWebView
作为 View Controller View 的 subview ,那么这可以正常工作。如果我再添加
UIWebView
作为 View Controller View 的 subview ,然后是 UIToolbar
没有出现,我也没有得到动画效果。 UIWebView
响应触摸但子类 UIView
才不是。但是,通知确实被触发了,并且导航栏确实被隐藏了。安排这些 subview 的最佳方法是什么,以便:
UIToolbar
可以在屏幕上下滑动UIWebView
is visible 仍然可以接收其典型的触摸事件:放大/缩小和双击以重置缩放级别 正确答案将满足这两个标准。
编辑
我在这方面取得了一些进展,但我无法区分触摸事件,因此我在不应该触发时触发了工具栏隐藏/显示方法。
我将 View Controller 的 view 属性设置为
UIView
子类,我在 -subviews
的顶部插入了 web View 阵列通过 [self.view insertSubview:self.webView atIndex:0]
.我在
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:
被触发(以及放大或缩小 WebView )。我想做的是事业-toggleToolbarView:
仅在有仅触摸事件时触发。当我调用上述方法时
-hitTest:withEvent:
,看起来像 UIWebView
吸收接触。两人NSLog
声明显示UIView*
这是从父项 UIView*
返回的的 -hitTest:withEvent:
要么是 UIWebView
或 UIToolbar
(当它在屏幕上并被触摸时)。 touches
数组为空,因此无法区分触摸事件类型。还有一件事我会尝试,但我想在这里记录这次尝试,以防其他人有快速建议。感谢您的持续帮助。
编辑二
我在获得
UIWebView
方面取得了一些进展捏/缩放和响应双击。我还可以通过单击隐藏/显示工具栏。而不是搞乱
UIWebView
实例的私有(private) UIScroller
,我访问它的内部,私有(private) UIWebDocumentView
.但是整个 WebView 在放大后无法正确重绘。这意味着:如果我的文档包含 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;
在覆盖 View 的实现中,我覆盖了
-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];
}
在 View Controller 中,我执行以下操作:
ViewerOverlayView
并将其添加为 View Controller view
的 subview 属性(property)ViewerWebView
实例并将其插入 subview 数组的底部 ViewerOverlayView
View Controller 的 web View 的 web View 属性 所以现在我的透明
ViewerOverlayView
正确地将缩放/拉伸(stretch)/双击触摸事件传递给 ViewerWebView
实例的私有(private) UIWebDocumentView
实例。 UIWebDocumentView
然后调整大小。但是,内容不会使用新比例重绘自身。因此,基于矢量的内容(例如 PDF、SVG)在放大时看起来很模糊。
这是没有缩放的 View ,漂亮而清晰:
这是放大时 View 的样子,它不像没有所有这些自定义事件处理那样清晰:
有趣的是,我只能在两个缩放级别之间重新缩放。一旦我停止双击拉伸(stretch)以放大任何级别,它就会“回弹”到您在上图中看到的框架。
我试过
-setNeedsDisplay
在 ViewerWebView
及其内部 UIWebDocumentView
实例。两种方法调用都不起作用。尽管想避免使用私有(private)方法,但因为我想最终让这个应用获得批准,我也尝试了 this suggestion访问私有(private)
UIWebDocumentView
方法 -_webCoreNeedsDisplay
:[(UIWebDocumentView *)self.webDocumentView _webCoreNeedsDisplay];
此方法导致应用程序从
unrecognized selector
崩溃异常(exception)。也许苹果已经将这个方法的名称从 SDK 3.0 更改为 3.1.2。除非有办法让 web View 重绘其内容,否则我想我将不得不废弃透明覆盖 View 并只绘制一个 web View ,以便让 web View 正常工作。真糟糕!
如果有人对缩放后重绘有任何想法,请随时添加答案。
再次感谢大家的投入。顺便说一句,我并没有取消对这个问题的赏金——我不知道为什么它没有自动授予这个线程的第一个答案,因为我原本希望从以前的经验中发生。
编辑三
我发现这个网页显示 how to subclass the application window以便观察点击并将这些点击转发到 View Controller 。
没有必要在整个应用程序的任何地方实现它的委托(delegate),只有在我想观察
UIWebView
上的点击的地方才需要实现。 ,因此这对于文档查看器可能非常有效。到目前为止,我可以观察点击、隐藏和显示工具栏,以及
UIWebView
表现得像一个 WebView 。我可以放大和缩小 Web View ,并且可以正确重新渲染文档。虽然学习如何以更通用的方式管理点击会很好,但这看起来是一个非常好的解决方案。
最佳答案
我正在阅读您的问题的方式,您想拦截事件触发某些操作(动画工具栏、发布通知),同时允许事件也到达其自然目的地。
如果我尝试这样做,我会放 UIToolbar
直接作为UIViewController.view
的 subview . UIWebView
仍然是一个直接的 subview 。UIViewController.view
应该是 UIView
的子类,它需要覆盖
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
View 可以通过发送回您想要接收事件的 View (UIToolbar 或 UIWebView)来回避作为事件处理的一部分,同时您仍然有机会触发您想要的操作。
一个例子可能是:
- (UIView *)hitTest:(CGPoint) point withEvent:(UIEvent *)event {
UIView* subview = [super hitTest:point withEvent:event];
/* Use the event.type, subview to decide what actions to perform */
// Optionally nominate a default event recipient if your view is not completely covered by subviews
if (subview == self) return self.webViewOutlet;
return subview;
}
关于iphone - 什么可以将触摸传递到(并显示所有) subview ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1856411/