【问题标题】:How to block a gesture from superview to subview?如何阻止从超级视图到子视图的手势?
【发布时间】:2013-06-07 08:37:32
【问题描述】:

我正在编写一个模块,每次在视图上滑动时,都会添加两个视图大小为一半的子视图。这些子视图有自己的手势(例如:平移,...)。我第一次刷,没关系,因为没有创建任何子视图。但是一旦创建了子视图,每次我滑动时,滑动手势总是传递给它的子视图。 :(,所以我必须滑动2次才能划分。

我想知道有没有办法阻止滑动传递到它的子视图?谢谢。

更新
我使用 shouldRecognizeSimultaneouslyWithGestureRecognizer 使这些手势同时工作。但是还是有一些问题。父视图有它的滑动手势,子视图有它的平移手势。由于我使用了 souldRecognizeSimultaneouslyWithGestureRecognizer,所以有时在我平移时,会触发滑动手势。那么,您知道在这种情况下如何在 Pan 处于活动状态时禁用 Swipe 吗?

【问题讨论】:

  • 你想要什么行为?如果子视图和父视图中都有手势识别器,显然存在冲突。
  • 我只希望在父视图中滑动行为,而不是子视图。我没有将此手势添加到子视图中。

标签: ios uiview uigesturerecognizer


【解决方案1】:

你必须实现 UIGestureRecognizerDelegate 方法:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer;

并将您的控制器添加为手势识别器的代表。然后,当两个手势识别器响应一个手势时,将调用此方法,您可以在此处为您的应用实现所需的逻辑。

在控制器的接口声明中你必须输入:

@interface testcViewController () <UIGestureRecognizerDelegate>

那么,在创建手势识别器时:

UISwipeGestureRecognizer *swipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipe)];
swipe.direction = UISwipeGestureRecognizerDirectionDown;
swipe.delegate = self;
[self.view addGestureRecognizer:swipe];

然后,最后,将此方法添加到控制器:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    BOOL shouldInteract = NO;
    //Here you decide whether or not the two recognizers whould interact.
    return shouldInteract;
}

编辑 你也可以实现

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer;

在这里,检测您是否已经呈现了子视图,并阻止您想要的任何手势。

【讨论】:

    【解决方案2】:

    为了阻止来自超级视图的所有手势识别器,我创建了一个 UIGestureRecognizer 子类,它在附加到视图时会执行此操作。请参阅以下代码(取自我的 WEPopover 项目):

    #import "WEBlockingGestureRecognizer.h"
    #import <UIKit/UIGestureRecognizerSubclass.h>
    
    @implementation WEBlockingGestureRecognizer
    
    - (id)init {
        return [self initWithTarget:self action:@selector(__dummyAction)];
    }
    
    - (id)initWithTarget:(id)target action:(SEL)action {
        if ((self = [super initWithTarget:target action:action])) {
            self.cancelsTouchesInView = NO;
        }
        return self;
    }
    
    -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
        if (self.state == UIGestureRecognizerStatePossible) {
            self.state = UIGestureRecognizerStateBegan;
        }
    }
    
    -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
    }
    
    -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
        self.state = UIGestureRecognizerStateRecognized;
    }
    
    - (BOOL)canBePreventedByGestureRecognizer:(UIGestureRecognizer *)preventingGestureRecognizer {
        return [self isGestureRecognizerAllowed:preventingGestureRecognizer];
    }
    
    - (BOOL)canPreventGestureRecognizer:(UIGestureRecognizer *)preventedGestureRecognizer {
        return ![self isGestureRecognizerAllowed:preventedGestureRecognizer];
    }
    
    - (BOOL)shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
        return ![self isGestureRecognizerAllowed:otherGestureRecognizer];
    }
    
    - (BOOL)shouldRequireFailureOfGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
        return NO;
    }
    
    - (BOOL)isGestureRecognizerAllowed:(UIGestureRecognizer *)gr {
        return [gr.view isDescendantOfView:self.view];
    }
    
    - (void)__dummyAction {
    
    }
    
    @end
    

    如果您想阻止附加到某个视图的父视图的所有手势识别器,只需执行以下操作:

    - (void)blockParentGesturesForView:(UIView *)v {
        [v addGestureRecognizer:[WEBlockingGestureRecognizer new]];
    }
    

    【讨论】:

    • 好主意,这让手势看起来像事件链,子视图会阻止超级视图手势。
    【解决方案3】:

    将 userinteractionEnabled 设置为子视图的 NO

     subview.userinteractionEnabled=NO
    

    如果您不想禁用 userInteraction,请使用cancelsTouchesInView 方法

    cancelsTouchesInView——如果手势识别器识别出它的手势, 它会从他们的视野中解除该手势的剩余触摸(所以 窗口不会提供它们)。窗口取消之前的 使用 (touchesCancelled:withEvent:) 消息传递触摸。如果一个 手势识别器无法识别其手势,视图接收到 多点触摸序列中的所有触摸。

    【讨论】:

    • 所以它也会禁用子视图手势。我不想那样。我希望子视图可以交互。
    • 子视图也有手势识别器,因此必须启用用户交互。
    【解决方案4】:

    试试这样,

       - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
        return NO;
    }
    

    【讨论】:

      【解决方案5】:

      考虑到我有一个dialogView 作为我的UIViewController 的主要view 的直接子视图,我将手势识别器附加到主要view 并执行以下操作(将我的视图控制器设置为手势识别器delegate):

      func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
          let point = touch.location(in: view)
          return !dialogView.frame.contains(point)
      } 
      

      【讨论】:

        【解决方案6】:

        采用我在这里阅读的内容并制作了一个非常棒的 Swift 5(对我来说)!我在一个视图中有一个滑动控件,该控件也有一个用于移动到另一个视图的滑动识别器。如果手指没有碰到滑块的拇指,则整个视图都会移动。

        通过将此视图放置在滑块下方(已展开使其更大一些),未命中不会有任何作用。

        final class BlockingView: UIView, UIGestureRecognizerDelegate {
            let swipe: UISwipeGestureRecognizer = UISwipeGestureRecognizer();
        
            init() {
                super.init(frame: CGRect.zero)
        
                swipe.direction = [.left, .right]
                self.addGestureRecognizer(swipe)
            }
            required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
        
            @objc override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { return false }
        }
        

        希望这可以为某人省去麻烦!

        【讨论】:

          猜你喜欢
          • 2013-06-25
          • 2020-09-28
          • 1970-01-01
          • 2020-07-21
          • 2019-07-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多