【问题标题】:UIGestureRecognizer subView recognizer problemUIGestureRecognizer subView 识别器问题
【发布时间】:2011-05-19 14:54:01
【问题描述】:

标题很难。 主要情况是这样的

UIView *superView = [[UIView alloc] initWithFrame:CGRectMake(0,0,400,400)];
UIView *subView = [[UIView alloc] initWithFrame:CGRectMake(-200,-200,400,400)];
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapAction:)];
[subView addGestureRecognizer:tapGesture];
[superView addSubView:subView];

OK,你会发现点击 (0,0,200,200) 中的区域时点击手势生效,如果点击点 (-150,-150) 则点击手势不生效。

不知道superView边界外的点击是否会导致这个问题。

有人知道如何解决这个问题吗?

【问题讨论】:

    标签: ios subview uigesturerecognizer


    【解决方案1】:

    要允许位于父视图之外的子视图响应触摸,请覆盖父视图的hitTest:withEvent:

    Documentation on Event Delivery

    触摸事件。窗口对象使用命中测试和响应者链来找到接收触摸事件的视图。在命中测试中,窗口在视图层次结构的最顶层视图上调用 hitTest:withEvent:;此方法通过在视图层次结构中返回 YES 的每个视图上递归调用 pointInside:withEvent: 来继续,沿着层次结构向下进行,直到找到在其范围内发生触摸的子视图。该视图成为命中测试视图。

    1. 创建 UIView 的子类。
    2. 覆盖 hitTest:withEvent。
    3. 将此 UIView 子类用于超级视图。

    在子类中添加下面的方法:

    (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
    {
        NSEnumerator *reverseE = [self.subviews reverseObjectEnumerator];
        UIView *iSubView;
    
        while ((iSubView = [reverseE nextObject])) {
    
            UIView *viewWasHit = [iSubView hitTest:[self convertPoint:point toView:iSubView] withEvent:event];
            if(viewWasHit) {
                return viewWasHit;
            }
    
        }
        return [super hitTest:point withEvent:event];
    }
    

    注意:使用反向枚举器,因为子视图是从后到前排序的,我们想先测试最前面的视图。

    【讨论】:

      【解决方案2】:

      对于这种情况,我发现的唯一解决方法是创建一个对触摸透明的视图实例作为主视图。在这种情况下,内部视图将响应触摸,因为它适合 main 的边界。在我从网上找到的不同示例中制作的课程中,我可以控制“触摸可见性”的级别,如下所示: 完全可见 - 所有的触摸都在视图中结束。 只有子视图 - 视图本身是不可见的,但子视图得到了影响。 完全不可见 - 我认为非常不言自明:)

      我没有尝试将它与手势识别器一起使用,但我认为不会有任何问题,因为它可以完美地与常规触摸配合使用。

      代码很简单……

      TransparentTouchView.h

      #import <UIKit/UIKit.h>
      
      typedef enum{
          TransparencyTypeNone = 0,         //act like usual uiview
          TransparencyTypeContent,          //only content get touches
          TransparencyTypeFull              //fully transparent for touches
      }TransparencyType;
      
      @interface TransparentTouchView : UIView {
          TransparencyType      _transparencyType;
      }
      
      @property(nonatomic,assign)TransparencyType transparencyType;
      
      @end
      

      TransparentTouchView.m

      #import "TransparentTouchView.h"
      
      
      @implementation TransparentTouchView
      
      @synthesize 
      transparencyType = _transparencyType;
      
      - (id)initWithFrame:(CGRect)frame{
          self = [super initWithFrame:frame];
          if (self) {
              // Initialization code
              self.backgroundColor = [UIColor clearColor];
          }
          return self;
      }
      
      - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
          // UIView will be "transparent" for touch events if we return NO
          switch (_transparencyType) {
              case TransparencyTypeContent:
                  for(UIView* subview in self.subviews){
                      CGPoint p = [subview convertPoint:point fromView:self];
                      if([subview pointInside:p withEvent:event]){
                          return YES;
                      }
                  }
                  return NO;
                  break;
              case TransparencyTypeFull:
                  return NO;
              default:
                  break;
          }
          return YES;
      }
      
      @end
      

      我相信你可以满足你的需要。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-06-04
        • 1970-01-01
        • 2011-11-12
        • 1970-01-01
        • 1970-01-01
        • 2020-07-11
        相关资源
        最近更新 更多