【问题标题】:UIButton touch is delayed when in UIScrollViewUIScrollView 中的 UIButton 触摸延迟
【发布时间】:2011-04-08 05:43:18
【问题描述】:

我在我的应用程序中遇到了一个小问题。

我基本上有一系列UIButtons 作为子视图添加到作为笔尖一部分的UIScrollView 中。每次我点击一个按钮时,在按钮突出显示之前都会有明显的延迟。在按钮变暗并显示为选中之前,我基本上必须按住它大约半秒钟。

我假设这是因为UIScrollView 需要确定触摸是滚动还是用于子视图的触摸。

无论如何,我有点不确定如何进行。我只是希望按钮在我点击后立即显示为选中状态。

感谢任何帮助!

编辑:

我尝试将 delaysContentTouches 设置为 NO,但滚动几乎变得不可能,因为我的大部分 scrollView 都充满了 UIButtons

【问题讨论】:

标签: ios uiscrollview uibutton touchescancelled


【解决方案1】:

Jeff 的解决方案不太适合我,但这个类似的解决方案可以:http://charlesharley.com/2013/programming/uibutton-in-uitableviewcell-has-no-highlight-state

除了在滚动视图子类中覆盖touchesShouldCancelInContentView,您还需要将delaysContentTouches 设置为false。最后,您需要为按钮返回true 而不是false。这是来自上述链接的修改示例。正如评论者所建议的那样,它专门检查 UIControl 的任何子类而不是 UIButton,以便此行为适用于任何类型的控件。

目标-C:

- (instancetype)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        self.delaysContentTouches = false;
    }

    return self;
}

- (BOOL)touchesShouldCancelInContentView:(UIView *)view {
    if ([view isKindOfClass:UIControl.class]) {
        return true;
    }

    return [super touchesShouldCancelInContentView:view];
}

斯威夫特 4:

override func touchesShouldCancel(in view: UIView) -> Bool {
    if view is UIControl {
        return true
    }
    return super.touchesShouldCancel(in: view)
}

【讨论】:

  • 这对我有用,而不是公认的答案。谢谢。
  • 优秀的解决方案!如果您使用的是界面生成器,只需选择滚动视图并取消选中属性检查器中的“延迟内容触摸”。
  • 测试了在 iOS 8 上发布的所有解决方案。只有这一个可以防止按钮上的触摸延迟并且不会干扰滚动。
  • 这就是解决方案。您可以获得类似跳板的效果(触摸动画提前开始,没有任何延迟,但如果您仍然决定滚动则取消)。
  • 如果视图是 UIControl 就更好了
【解决方案2】:

好的,我已经通过继承 UIScrollView 并覆盖 touchesShouldCancelInContentView 解决了这个问题

现在我的UIButton 被正确标记为 99 个亮点,我的滚动视图正在滚动!

myCustomScrollView.h

@interface myCustomScrollView : UIScrollView  {

}

@end

myCustomScrollView.m

@implementation myCustomScrollView

    - (BOOL)touchesShouldCancelInContentView:(UIView *)view
    {
        NSLog(@"touchesShouldCancelInContentView");

        if (view.tag == 99)
            return NO;
        else 
            return YES;
    }

【讨论】:

  • 哇,我刚刚遇到了这个答案,它完全解决了我遇到的问题。希望我能给你+1000分!非常感谢。
  • 在我的情况下不起作用,但它非常接近你的。(仅在模拟器中测试)。也许这个解决时间已经到了。
【解决方案3】:

尝试将 UIScrollView delaysContentTouches 属性设置为 NO。

【讨论】:

  • 对不起,我可能应该更清楚。如果我将 delaysContentTouches 设置为 NO,触摸会立即响应。然而,滚动几乎变得不可能,因为触摸被解释为按钮按下而不是实际滚动。
  • @Jeff 您可以使用canCancelContentTouches 来允许滚动,即使触摸最初被视为按钮触摸,只要触摸的目标支持取消。最初触摸时按钮仍会突出显示,但一旦您开始滚动就会取消突出显示。
  • @chaiguy 我正在寻找这种行为,就像你描述的那样,但到目前为止还没有运气。如果我设置 delaysContentTouches = NOcanCancelContentTouches = YES 我在触摸 UIButton 时根本无法滚动。
  • @Darrarski 抱歉,我想的是UITableViewCell,而不是UIButton。看起来该按钮不支持取消的触摸,因为它允许您拖动按钮以取消它,从而覆盖接收拖动的滚动视图。我不确定如何使用UIButton 来实现这一点,但您可以通过子类化UIButton 来实现。
【解决方案4】:

故事板解决方案:选择滚动视图,打开“属性检查器”并取消选中“延迟内容触摸”

【讨论】:

    【解决方案5】:

    在 Swift 3 中:

    import UIKit
    
    class ScrollViewWithButtons: UIScrollView {
    
        override init(frame: CGRect) {
            super.init(frame: frame)
            myInit()
        }
    
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
            myInit()
        }
    
        private func myInit() {
            self.delaysContentTouches = false
        }
    
        override func touchesShouldCancel(in view: UIView) -> Bool {
            if view is UIButton {
                return true
            }
            return super.touchesShouldCancel(in: view)
        }
    }
    

    然后您可以在 IB 或代码中使用此 ScrollViewWithButtons

    【讨论】:

      【解决方案6】:

      斯威夫特 3:

      scrollView.delaysContentTouches = false
      

      【讨论】:

        【解决方案7】:

        现有的解决方案都不适合我。也许我的情况比较特殊。

        UIScrollView 中有很多 UIButtons。当按下UIButton 时,会向用户呈现一个新的UIViewController。如果一个按钮被按下并保持足够长的时间,该按钮将显示其按下状态。我的客户抱怨说,如果你点击太快,不会显示抑郁状态。

        我的解决方案: 在UIButtons'tap 方法中,我加载新的UIViewController 并将其呈现在屏幕上,我使用

        [self performSelector:@selector(loadNextScreenWithOptions:) 
                   withObject:options 
                   afterDelay:0.]
        

        这会安排在下一个事件循环中加载下一个 UIViewController。留出时间让UIButton 重绘。 UIButton 现在在加载下一个 UIViewController 之前显示其沮丧状态。

        【讨论】:

          猜你喜欢
          • 2011-03-06
          • 1970-01-01
          • 2016-09-07
          • 2016-04-24
          • 1970-01-01
          • 2013-03-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多