我有以下子视图链:
UIViewController.view -+
|-> UIView (subclass) -+
| +-> UIToolbar
|
+------------------------> UIWebView
在子类中,我重写了它的-touchesEnded:forEvent:
方法,以便在UIToolbar
单击时隐藏和显示,通过 a CAAnimation
,以及发出一个NSNotification
导致视图控制器隐藏其导航栏的问题。
如果我不将UIWebView
作为子视图添加到视图控制器的视图中,那么它可以正常工作。
如果我然后添加UIWebView
作为视图控制器视图的子视图,则UIToolbar
不会出现,并且我没有获得动画效果。UIWebView
响应触摸,但子类不UIView
响应。但是,通知确实被触发了,并且导航栏确实被隐藏了。
安排这些子视图的最佳方法是什么,以便:
UIToolbar
可以在屏幕上滑动和滑出- 可见仍然可以接收其
UIWebView
典型的触摸事件:放大/缩小和双击以重置缩放级别
正确的答案将满足这两个标准。
编辑
我在这方面取得了一些进展,但我无法区分触摸事件,因此我在不应该触发工具栏隐藏/显示方法时触发它。
我将视图控制器的视图属性设置为UIView
子类,并-subviews
通过[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:
触发(以及放大或缩小 Web 视图)。我想做的是-toggleToolbarView:
仅在有仅触摸事件时才被触发。
当我调用上述方法-hitTest:withEvent:
时,它看起来像是在UIWebView
吸吮。这两个NSLog
语句表明UIView*
从 parent 返回的 theUIView*
是-hitTest:withEvent:
theUIWebView
或 the UIToolbar
(当它在屏幕上并被触摸时)。该touches
数组为空,因此无法区分触摸事件类型。
还有一件事我会尝试,但我想在这里记录一下这个尝试,以防其他人有快速的建议。感谢您的持续帮助。
编辑二
UIWebView
我在捏/缩放和双击响应方面取得了一些进展。我还可以通过单击隐藏/显示工具栏。
我没有弄乱UIWebView
实例的 private UIScroller
,而是访问它的内部 private UIWebDocumentView
。但是放大后,整个 Web 视图无法正确重绘。
这意味着:如果我的文档包含 PDF 或 SVG 矢量图,例如,放大会导致内容模糊,就好像构成渲染的 PDF 或矢量图内容的图像图块没有被重新渲染新的缩放系数。
为了记录这一点,我将:
UIView (subclass)
改为调用ViewerOverlayView
被
UIWebView
称为ViewerWebView
两者分别是UIView
和的子类UIWebView
。
MyViewerWebView
包含一个新的 ivar(带@property
+ @synthesized
):
UIView *privateWebDocumentView;
(这UIView
实际上是一个指向UIWebDocumentView
实例的指针,但为了避免 Apple 将应用程序标记为拒绝,我将其转换为 a 只是UIView
为了传递触摸事件。)
ViewerWebView
覆盖的实现-hitTest:withEvent:
- (UIView *) hitTest:(CGPoint)point withEvent:(UIEvent *)event {
UIView *_subview = [super hitTest:point withEvent:event];
self.privateWebDocumentView = _subview;
return _subview;
}
MyViewerOverlayView
包含新的 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)在放大时看起来很模糊。
这是没有缩放的视图,漂亮而清晰:
这是放大后的视图,它不像没有所有这些自定义事件的情况下那样清晰:
有趣的是,我只能在两个缩放级别之间重新缩放。一旦我停止双击拉伸以放大任何级别,它就会“弹回”到您在上图中看到的帧。
我尝试-setNeedsDisplay
了ViewerWebView
及其内部UIWebDocumentView
实例。两种方法调用都不起作用。
尽管想避免使用私有方法,但因为我希望最终获得该应用程序的批准,我也尝试了访问私有方法的建议:UIWebDocumentView
-_webCoreNeedsDisplay
[(UIWebDocumentView *)self.webDocumentView _webCoreNeedsDisplay];
此方法导致应用程序因unrecognized selector
异常而崩溃。或许 Apple 已将此方法的名称从 SDK 3.0 更改为 3.1.2。
除非有办法让 web 视图重绘其内容,否则我想我将不得不废弃透明覆盖视图并只绘制一个 web 视图,以使 web 视图正常工作。太糟糕了!
如果有人对缩放后重绘有想法,请随时添加答案。
再次感谢大家的意见。顺便说一句,我没有取消这个问题的赏金——我不知道为什么它没有自动授予这个线程的第一个答案,因为我原本期望从以前的经验中发生这种情况。
编辑三
我发现这个网页显示了如何对应用程序窗口进行子类化,以便观察点击并将这些点击转发到视图控制器。
没有必要在整个应用程序的任何地方都实现它的委托,只需要在我想观察点击的地方实现它UIWebView
,所以这对于文档查看器来说可能非常有效。
到目前为止,我可以观察点击、隐藏和显示工具栏,其UIWebView
行为类似于 web 视图。我可以放大和缩小 Web 视图,并且正确地重新呈现文档。
虽然学习如何以更通用的方式管理水龙头会很好,但这看起来是一个非常棒的解决方案。