【问题标题】:How to pass the touch event to superview when userInteractionEnabled = YES?userInteractionEnabled = YES时如何将触摸事件传递给superview?
【发布时间】:2014-05-06 14:23:54
【问题描述】:

我有以下设置。

+- XXXCustomControl : UIControl -------+
| A                                    |
|   +- ContentView -------------------+|
|   |                                 ||
|   |  B                              ||
|   |                                 ||
|   +---------------------------------+|
+--------------------------------------+ 

作为 UIControl 子类的 XXXCustomControl。它包含一个名为 contentView 的 UIView 类型的子视图,其大小小于控件的区域。 那个视图有.userInteractionEnabled = YES;

我需要将该属性设置为 YES,因为水平滚动视图偶尔会放在其中,并且它们需要是可滚动的。如果超级视图(在我们的例子中,内容视图不允许用户交互,这会被子视图继承。) 但与此同时,这个XXXCustomControl 需要在其内容视图中不包含滚动视图时(不仅在区域 A 中,而且在区域 B 中)是可点击的。

所以我在这里有“利益冲突”,因为我要么

1)将内容视图设置为userInteractionEnabled = NO,然后我可以在A和B的内容视图区域中点击空控件,但是我将放置在那里的滚动视图将无法滚动。..

2)将内容视图设置为userInteractionEnabled = YES,但是如果控件为空,我只能点击区域A来触发触摸事件。

我想出的一个想法是,我将属性默认设置为 NO,当我填充 contentView 时,我将其设置为 yes。当我清除 contentView 时,我将属性设置回 no。 基本上我希望它一直设置为yes,当它为空时,强制contentView将touchUpInside事件传递给它的superview。

这可能吗?

【问题讨论】:

  • 如果你只关心点击,为什么不向子视图添加一个手势识别器,它的动作与父视图中的手势识别器相同?这似乎是最简单的实现。
  • 你为什么不给答案?迈克尔为我工作......
  • 迟到总比不到好...
  • 我认为这不是利益冲突的定义,也许是利益冲突? :)

标签: ios objective-c swift cocoa-touch


【解决方案1】:

您可以尝试在内部视图中覆盖pointInside:withEvent: 方法。当您想将触摸转发到超级视图时,这将允许您返回 NO:

-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
    if( /* You have content, and you want to receive touches */){
        return YES;
    }else{
        return NO;
    }
}

【讨论】:

  • 这也适用于包含在容器视图中的视图 - 允许某些控件存在于容器(超级)视图中。只需通过子视图帧进行交互 - 如果没有命中则返回 NO
【解决方案2】:

您可以子类化您的子视图,并实现

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    if (!touchedContent) {
        [[self nextResponder] touchesBegan:touches withEvent:event];
    } else {
        [super touchesBegan:touches withEvent:event];
    }
}

【讨论】:

    【解决方案3】:

    您可以使用另一个 UIView 来“隐藏”子视图。

    *详细信息:这个 UIView 是子视图的兄弟。它与您的子视图具有相同的大小和位置,背景颜色为透明色。

    *说明:新的 UIView 将进行触摸,并自动将其传递给父视图。

    这种方式不需要子类化您的子视图 - 这是一个故事板解决方案。
    请试试这个。玩得开心!

    【讨论】:

      【解决方案4】:

      在超级视图中使用它,无需更改子视图代码(因为子视图可​​能从其他框架或 pod 引入):

      - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
      {
          UIView *view = [super hitTest:point withEvent:event];
          if ([view isDescendantOfView:self])
          {
              NSLog(@"touched inside");
          }
          return view;
      }
      

      【讨论】:

        【解决方案5】:

        - 斯威夫特

        override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
            if <#condition#> { return true }
            else { return false }
        }
        

        【讨论】:

          【解决方案6】:

          如果您想从超级视图(在您的情况下为 XXXCustomControl)而不是内部视图(在您的情况下为 ContentView)处理事件,您可以在您的超级视图中编写以下 swift 代码:

          override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
              guard let view = super.hitTest(point, with: event) else { return nil }
              if view.isDescendant(of: self) {
                  // your custom logic
              }
              return view
          }
          

          【讨论】:

            猜你喜欢
            • 2019-08-09
            • 2012-07-19
            • 1970-01-01
            • 2012-02-08
            • 1970-01-01
            • 2011-09-16
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多