首页 > 解决方案 > 在*子视图*中禁用手势识别器,以便超级视图手势识别器可以运行

问题描述

我有一个 NSView(画布),我将一组 TextView 子类(小盒子)放入其中。TextView 类上有用于拖放(移动)和选择的 GestureRecognizers。

画布有两种模式:

在文本模式下,我可以与 TextView 类进行交互——我可以点击它们、编辑等。

当我切换到绘图模式时,我想完全禁用 TextView 框,并让 Canvas 捕获所有事件/手势。

这样我就可以在整个画布上执行 Pan/Click 事件,并且 TextView 框应该是可见的,但否则会被忽略/禁用。

要进入绘图模式,我按如下方式禁用 TextView 框(如果布尔“绘图”为真,则我关闭 TextView 框中的所有事件处理):

            foreach (var tv in textBoxes)
            {
                tv.Editable = !drawing;
                tv.Selectable = !drawing;

#if __IOS__
                tv.UserInteractionEnabled = !drawing;
#else
                tv.AcceptsTouchEvents = !drawing;
#endif
                foreach (var g in tv.GestureRecognizers)
                    g.Enabled = !drawing;
            }

因此,iOS 上的两种模式之间的一切都可以完美运行。在 Mac 上,一切都可以正常工作,但有一个例外:在绘图模式下(当 textview 和 textview 手势被禁用时),如果我在 TextView 框顶部开始一个手势,则什么也不会发生。Canvas 手势处理程序和 TextView 框手势处理程序均未被调用。在其他任何地方开始一个手势都可以正常工作,并且 Canvas 手势处理程序会接收它。

总之,我的问题是:我怎样才能完全禁用子视图中的手势,以便识别超级视图手势,即使手势从子视图顶部开始。

有将手势传递给子视图的示例,但在这里我想将手势传递给超级视图(我认为它应该是响应者链的顶部)。

任何建议将不胜感激。

标签: xcodemacos

解决方案


似乎解决方案是确保您要接收手势的子视图必须位于顶部,否则手势似乎无法到达它(这意味着它必须是 Subviews 数组中的最后一项)。

换句话说,如果另一个子视图“A”位于您的子视图“B”之上 - 并且该子视图“A”完全禁用,没有手势识别器......它将阻止“B”中的任何手势被识别。

手势识别器不应该使用响应者链......(这在 UIGestureRecognizer 规范中明确,但不是NSGestureRecognizer 规范)。这是后者的引述:

您的应用收到的事件会在发送到相应视图之前自动转发到任何相关的手势识别器

这并没有讨论事件如何在 Mac 上的手势识别器的响应者链中向上流动。

所以如上所述 - 将您的子视图放在前面以确保其手势将被识别。在 Mac 上,没有办法轻松地订购 NSView 的子视图(不像 UIView 具有bringToFront、sendToBack 等)。所以我发现最好的方法是使用带有适当排序功能的 SortSubviews。


推荐阅读