【问题标题】:Passing touches between stacked UIWindows?在堆叠的 UIWindows 之间传递触摸?
【发布时间】:2013-02-06 23:33:29
【问题描述】:

我有两扇窗户——前一扇,后一扇。前面的用于在后面的上面覆盖一些东西。我希望能够捕捉到前窗某些部分的触摸,而不是其他部分;我希望前窗在某些区域接收触摸,但在其他区域将它们传递到后窗。

关于我如何做到这一点的任何想法?

【问题讨论】:

  • 你为什么用2个窗口?
  • 它是一个 SDK 的一部分,显示在宿主应用程序的覆盖层上——我们无法触及宿主应用程序的视图层次结构。
  • 您有没有找到实现这一目标的方法?如果是这样,即使您没有时间写出完整的答案,您是否至少可以给我们一个漫游路径的提示?

标签: ios uiview touch uiwindow


【解决方案1】:

好的,这就是我所做的:我在前窗口中创建了两个视图。第一个视图覆盖了我想要捕捉的区域;第二个,我希望触摸通过的地方。我将 UIWindow 子类化并覆盖了 hitTest:withEvent 方法,如下所示:

- (UIView *) hitTest:(CGPoint)point withEvent:(UIEvent *)event {

  // See if the hit is anywhere in our view hierarchy
  UIView *hitTestResult = [super hitTest:point withEvent:event];

  // ABKSlideupHostOverlay view covers the pass-through touch area.  It's recognized
  // by class, here, because the window doesn't have a pointer to the actual view object.
  if ([hitTestResult isKindOfClass:[ABKSlideupHostOverlayView class]]) {

    // Returning nil means this window's hierachy doesn't handle this event. Consequently,
    // the event will be passed to the host window.
    return nil;
  }

  return hitTestResult;
}

在创建前窗口的类中,我使用手势识别器来捕捉对第一个视图的触摸。


2017 年代码相同:

class PassView: UIView {}

class UIHigherWindow: UIWindow {

    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {

        let hitView = super.hitTest(point, with: event)

        if hitView!.isKind(of: PassView.self) {

            return nil
        }

        return hitView
    }
}

您的“uber”窗口将是一些视图控制器,UberVc。

只要把UberVc的主视图(也就是背景.view)做成PassView就行了。

然后在 UberVc 上添加说按钮等。

上面的代码会导致对按钮的任何点击进入 UberVc,而对按钮以外的任何点击(即“背景”)都会进入您的常规窗口/VC。

【讨论】:

  • 如果您的解决方案是在底部窗口中有一个文本字段的 Web 视图,它是否有效?当您按下键盘附带的“完成”按钮时?
  • 不知道——这个答案是三年前的。 ? 试一试并发布您的结果! ?
  • 它没有:\,这就是为什么我想看看是否有人弄清楚了:p
  • 壮观,安娜。我输入了一些最新的 swift 代码;随意编辑/放松等当然...干杯,谢谢!!!
  • 赏金正在寻找惊人的答案!
【解决方案2】:

我有一个类似的问题:额外的 UIWindow 应该有一个透明的视图,并带有一些难以处理的子视图。必须通过这些棘手视图之外的所有触摸。

我最终使用了 Anna 代码的修改版本,它使用视图的标签而不是类型检查。这种方式不需要创建视图子类:

class PassTroughWindow: UIWindow {
    var passTroughTag: Int?

    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {

        let hitView = super.hitTest(point, with: event)

        if let passTroughTag = passTroughTag {
            if passTroughTag == hitView?.tag {
                return nil
            }
        }
        return hitView
    }
}

假设您创建了一个窗口和根视图控制器,您可以像这样使用它:

let window: PassTroughWindow 
//Create or obtain window

let passTroughTag = 42

window.rootViewController.view.tag = passTroughTag
window.passTroughTag = passTroughTag

//Or with a view:
let untouchableView: UIView // Create it
untouchableView.tag = passTroughTag
window.addSubview(untouchableView)

【讨论】:

    【解决方案3】:

    不要使用多个 UIWindows,而是使用 [[UIApplication sharedApplication] keyWindow] 获取关键窗口,然后将您的视图添加到其中:

    mainWindow = [[UIApplication sharedApplication] keyWindow];
    [mainWindow addSubview:view]
    

    【讨论】:

    • 我试过了,但并非在所有情况下都有效:您的视图上会出现一个弹出框。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多