gpt4 book ai didi

iphone - 什么可以将触摸传递到(并显示所有) subview ?

转载 作者:行者123 更新时间:2023-12-03 18:39:47 25 4
gpt4 key购买 nike

我有以下 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:要么是 UIWebViewUIToolbar (当它在屏幕上并被触摸时)。 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)
  • 实例化 View Controller 的 ViewerWebView实例并将其插入 subview 数组的底部
  • 设置 ViewerOverlayView View Controller 的 web View 的 web View 属性

  • 所以现在我的透明 ViewerOverlayView正确地将缩放/拉伸(stretch)/双击触摸事件传递给 ViewerWebView实例的私有(private) UIWebDocumentView实例。 UIWebDocumentView然后调整大小。

    但是,内容不会使用新比例重绘自身。因此,基于矢量的内容(例如 PDF、SVG)在放大时看起来很模糊。

    这是没有缩放的 View ,漂亮而清晰:

    UIWebView, no scaling

    这是放大时 View 的样子,它不像没有所有这些自定义事件处理那样清晰:

    UIWebView, blurry zoom

    有趣的是,我只能在两个缩放级别之间重新缩放。一旦我停止双击拉伸(stretch)以放大任何级别,它就会“回弹”到您在上图中看到的框架。

    我试过 -setNeedsDisplayViewerWebView及其内部 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/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com