触摸时Uibutton触摸向下操作未调用,但触摸移动时调用

问题描述 投票:8回答:7

当用户触摸DOWN UIButton时,您需要执行操作

[button addTarget:self action:@selector(touchDown:event:) forControlEvents:UIControlEventTouchDown];
[button addTarget:self action:@selector(drag:event:) forControlEvents:UIControlEventTouchDragInside];
[button addTarget:self action:@selector(drag:event:) forControlEvents:UIControlEventTouchDragOutside];
[button addTarget:self action:@selector(touchUp:event:) forControlEvents:UIControlEventTouchUpInside];
[button addTarget:self action:@selector(touchUp:event:) forControlEvents:UIControlEventTouchUpOutside];

- (void)touchDown:(UIButton *)sender event:(UIEvent *)event {
    //begin only called when I move my finger 
}


- (void)drag:(UIButton *)sender event:(UIEvent *)event {
    //called when I move my finger, after touchDown was called
}
- (void)touchUp:(UIButton *)sender event:(UIEvent *)event {

}

我的应用程序的根视图控制器是tabbarviewcontroller,每个选项卡都是导航视图控制器。在聊天场景的viewWillAppear方法中,我隐藏了标签栏。

结果是,在设备上,当我触摸时,它没有被调用,当我移动我的手指时,它被调用。

注意:

  1. 使用长按手势识别器也不起作用。
  2. 如果我将按钮远离标签栏区域,它可以在设备上运行。
  3. 在模拟器上,一切都很好。

我创建了一个示例项目:https://drive.google.com/folderview?id=0B_9_90avvmZtRmRDeHFkbFJLaFk&usp=sharing

ios objective-c cocoa-touch uikit
7个回答
11
投票

此按钮位于滚动视图内的任何位置(包括集合或tableview)吗?如果是这样,那就是预期的行为。系统等待您查看是否要点击按钮或拖动滚动视图。来自Apple:

因为滚动视图没有滚动条,所以它必须知道触摸是否表示滚动意图与跟踪内容中的子视图的意图。为了做出这种确定,它通过启动计时器暂时拦截触碰事件,并且在计时器触发之前,查看触摸手指是否进行任何移动。如果计时器在没有显着位置变化的情况下触发,则滚动视图将跟踪事件发送到内容视图的触摸子视图。如果用户在计时器过去之前将手指拖得足够远,则滚动视图会取消子视图中的任何跟踪并执行滚动操作。子类可以覆盖touchesShouldBegin:withEvent:inContentView:pagingEnabled,touchesShouldCancelInContentView:方法(由滚动视图调用)以影响滚动视图如何处理滚动手势。

如果您不想要这种行为,可以将parentview.delaysContentTouches设置为NO您可能还需要将canCancelContentTouches设置为NO


9
投票

嗨@OMGPOP我有同样的问题,现在我已经解决了它添加下面的代码:

self.navigationController.interactivePopGestureRecognizer.delaysTouchesBegan = NO;

我确定这是你的救世主,因为我已下载你的示例代码并添加上面的代码,它工作正常。像这样:

self.navigationController.interactivePopGestureRecognizer.delaysTouchesBegan = NO;


[self.holdToRecordButton addTarget:self action:@selector(touchDown:event:) forControlEvents:UIControlEventTouchDown];
[self.holdToRecordButton addTarget:self action:@selector(drag:event:) forControlEvents:UIControlEventTouchDragInside];
[self.holdToRecordButton addTarget:self action:@selector(drag:event:) forControlEvents:UIControlEventTouchDragOutside];
[self.holdToRecordButton addTarget:self action:@selector(touchUp:event:) forControlEvents:UIControlEventTouchUpInside];
[self.holdToRecordButton addTarget:self action:@selector(touchUp:event:) forControlEvents:UIControlEventTouchUpOutside];

0
投票

你的按钮上有任何子视图吗?这些可能会拦截触摸并导致您看到的行为。


0
投票

您的按钮超级视图上是否有任何UIGestureRecognizers?它们可能导致这种延迟。


0
投票

我遇到了同样的问题,最终弄明白了。

这里的问题是按钮无法接收动作,因为滚动视图手势识别器可能会使观察者变黑。

您需要做的是在音频按钮的容器上添加手势,将手势识别器委托设置到视图控制器,并将导航控制器弹出手势识别器黑屏,如下所示。

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{
  if ([UIDevice currentDevice].isIOS7 && touch.view == btnAudioRecorder)//issue is iOS7 only{
     self.navigationController.interactivePopGestureRecognizer.enabled = NO;
  }
 return YES;
}

然后查看它,按钮现在可以像魅力一样回答您的触地事件。


0
投票

我有同样的问题并解决了它。

在我的情况下,有两个相邻的按钮。 (左按钮是按钮A.右按钮是按钮。)按钮不称为按下触发事件。但是Button被称为触碰事件。

我尝试在ButtonB类中重写pointInside

override func pointInside(point: CGPoint, withEvent event: UIEvent?) -> Bool {
    println(point)
}

然后,我点击了buttonA并调用了ButtonB的pointInside !! point.x是负值。

所以我在ButtonB类中检查了point和sendAction。

override func pointInside(point: CGPoint, withEvent event: UIEvent?) -> Bool {
    if CGRectContainsPoint(self.bounds, point) {
        return true
    }

    // hoge.left means hoge.frame.origin.x
    if point.x < 0, let buttonA = optionalButtonA {
        buttonA.bounds.origin.x -= (self.left - buttonA.left) //self.left is buttonB.left
        if CGRectContainsPoint(buttonA.bounds, point) {
            buttonA.sendActionsForControlEvents(UIControlEvents.TouchDown)
            return false
        }
    }
    return false
}

0
投票

我遇到过同样的问题。并尝试了所有的答案,但没有一个工作。幸运的是,我的同事有同样的问题,他解决了!

解决方案是:

将以下代码放在相对的ViewController中:

override var preferredScreenEdgesDeferringSystemGestures: UIRectEdge {
    return .bottom
}

override func viewDidLoad() {
    super.viewDidLoad()
    self.navigationController?
        .interactivePopGestureRecognizer?
        .delaysTouchesBegan = false
}

当您的按钮位于屏幕底部下方时,可能会立即调用触碰操作的原因,触碰事件将与iOS从底部手势向上滑动冲突。所以它推迟了。

© www.soinside.com 2019 - 2024. All rights reserved.