Ale*_*lds 7 iphone uiwebview uitoolbar uiviewcontroller uiview
我有以下子视图链:
UIViewController.view -+
|-> UIView (subclass) -+
| +-> UIToolbar
|
+------------------------> UIWebView
Run Code Online (Sandbox Code Playgroud)
在子类中,我重写其-touchesEnded:forEvent:方法以隐藏和显示UIToolbar单击点击触摸,通过a CAAnimation,以及发出NSNotification导致视图控制器隐藏其导航栏的方法.
如果我不将UIWebView子视图作为子视图添加到视图控制器的视图中,则可以正常工作.
如果我然后添加UIWebView视图控制器的视图的子视图,然后UIToolbar没有出现,我没有得到动画效果.在UIWebView以触摸响应,但子类UIView没有.但是,通知会被触发,导航栏会被隐藏.
安排这些子视图的最佳方法是:
UIToolbar可以使打开和关闭滑动屏幕UIWebView放大/缩小和双击重置缩放级别:仍可获得其典型的触摸事件是可见正确的答案将符合这两个标准.
编辑
我在这方面取得了一些进展,但我无法区分触摸事件,因此我不应该触发工具栏隐藏/显示方法.
我将视图控制器的视图属性设置为UIView子类,然后-subviews通过将数组顶部的Web视图插入[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;
}
Run Code Online (Sandbox Code Playgroud)
该方法-toggleToolbarView:触发NSTimer定时限的CAAnimation隐藏/显示UIToolbar*.
问题是触摸拖动组合导致-toggleToolbarView:被触发(以及放大或缩小Web视图).我想做的是-toggleToolbarView:只有在有触摸事件时才会被解雇.
当我打电话给上面的方法时-hitTest:withEvent:,它看起来很UIWebView糟糕.这两个NSLog报表显示,该UIView*是从返回父UIView*的-hitTest:withEvent:要么是UIWebView或UIToolbar(当它在屏幕上摸).该touches数组为空,因此,触摸事件类型不能被区分.
还有一件事我会尝试,但我想在这里记录这个尝试,以防其他人有快速建议.感谢您的继续帮助.
编辑二
我在UIWebView捏/缩放和响应双击方面取得了一些进展.我也可以用单击隐藏/显示工具栏.
而不是搞乱UIWebView实例的私有UIScroller,我访问它的内部私有UIWebDocumentView.但放大后,整个网页视图不会正确重绘.
这意味着:例如,如果我的文档包含PDF或SVG矢量插图,则放大会导致内容模糊,就好像构成渲染的PDF或矢量插图内容的图像切片不会重新渲染一样新的缩放系数.
为了记录这一点,我将:
调用UIView (subclass),而不是ViewerOverlayView
在UIWebView被称为ViewerWebView
两者都是UIView和的子类UIWebView.
我的ViewerWebView包含一个新的ivar(带@property+ @synthesized):
UIView *privateWebDocumentView;
Run Code Online (Sandbox Code Playgroud)
(这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;
}
Run Code Online (Sandbox Code Playgroud)
我的ViewerOverlayView包含新的ivars(带@property+ @synthesized):
ViewerWebView *webView;
UIView *webDocumentView;
Run Code Online (Sandbox Code Playgroud)
在覆盖视图的实现中,我重写-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];
}
Run Code Online (Sandbox Code Playgroud)
在视图控制器中,我执行以下操作:
实例化ViewerOverlayView并将其添加为视图控制器view属性的子视图
实例化视图控制器的ViewerWebView实例并将其插入子视图数组的底部
将ViewerOverlayViewWeb视图属性设置为视图控制器的Web视图
所以现在我的透明ViewerOverlayView正确地将缩放/拉伸/双击触摸事件传递给ViewerWebView实例的私有UIWebDocumentView实例.在UIWebDocumentView随后调整大小.
但是,内容不会使用新比例重绘.因此,基于矢量的内容(例如PDF,SVG)在放大时看起来很模糊.
这是视图看起来没有缩放,漂亮和锐利的样子:
以下是放大时视图的样子,如果没有所有这些自定义事件的话,它就不会像以前那样清晰:
有趣的是,我只能在两个缩放级别之间重新缩放.一旦我停止双击拉伸以放大任何级别,它就会"快速回退"到您在上图中看到的帧.
我尝试-setNeedsDisplay了ViewerWebView它的内部UIWebDocumentView实例.两种方法调用都不起作用.
尽管想要避免私有方法,因为我想最终获得批准的应用程序,我也尝试了访问私有方法的这个建议:UIWebDocumentView-_webCoreNeedsDisplay
[(UIWebDocumentView *)self.webDocumentView _webCoreNeedsDisplay];
Run Code Online (Sandbox Code Playgroud)
此方法导致应用程序从unrecognized selector异常中崩溃.也许Apple已将此方法的名称从SDK 3.0更改为3.1.2.
除非有办法让Web视图重绘其内容,否则我想我将不得不废弃透明覆盖视图并只绘制Web视图,以使Web视图正常工作.太糟糕了!
如果有人有关于重绘后缩放的想法,请随时添加答案.
再次感谢大家的投入.顺便说一句,我没有取消对这个问题的赏金 - 我不知道为什么它没有自动被授予这个帖子的第一个答案,因为我原本期望从以前的经验中发生.
编辑III
我发现这个网页显示了如何子类化应用程序窗口,以便观察点击并将这些点击转发到视图控制器.
没有必要在整个应用程序中的任何地方实现其委托,只有在我想要观察点击的地方UIWebView,所以这对于文档查看器可能非常有效.
到目前为止,我可以观察点击,隐藏和显示工具栏,并且UIWebView行为类似于Web视图.我可以放大和缩小Web视图,并正确地重新呈现文档.
虽然学习如何以更通用的方式管理水龙头会很好,但这看起来是一个非常好的解决方案.
我阅读您问题的方式是,您希望拦截事件以触发某些操作(动画工具栏、发布通知),同时允许事件也到达其自然目的地。
如果我尝试这样做,我会UIToolbar直接将 放置为 的子视图UIViewController.view。它UIWebView仍然是一个直接子视图。
应该UIViewController.view是 的子类UIView,并且需要重写
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
Run Code Online (Sandbox Code Playgroud)
视图可以通过发回您想要接收事件的视图(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;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
10732 次 |
| 最近记录: |