iOS UIButton在某些情况下不能立刻响应TouchDown事件

转载 2015年07月08日 16:54:06

转载:http://www.07net01.com/2015/04/814048.html

UIButton在某些情况下不能立刻响应TouchDown事件,换句话说,迅速点击按钮时,你是永远看不见这个按钮的高亮状态的。


而你会发现,出现这种情况时,这些按钮都在UIScrollView(UITableView)上。
为此我用了一下午时间查贴整理,得到了完美的解决方案。

在介绍解决方案前,必须先科普一些事实,帮助大家理解:
UIScrollView:
1、属性delaysContentTouches,布尔类型,默认值为YES。值为YES时,UIScrollView会在接收到手势时延迟150ms来判断该手势是否能够出发UIScrollView的滑动事件;值为NO时,UIScrollView会立马将接收到的手势分发到子视图上。
(注:仅仅设置这个是不够的,你会发现如果想要拖动scrollView而起点落在其他有手势识别的视图上时会拖不动)
2、方法- (BOOL)touchesShouldCancelInContentView:(UIView *)view,此方法的重载是帮助我们完美解决问题的重点,决定手势是否取消传递到view上,拖动ScrollView时触发。返回NO时,拖动手势将留在ScrollView上,返回YES则将手势传到view上。(若view是UIControl,则默认返回YES)

UITableView:
不得不说,UITableView(包括UITableViewCell在内)在iOS7和iOS8中的视图结构是不同的,且存在着很多我们在编码时永远接触不到的视图,但我们可通过Debug将其subviews逐个逐个找出来。这关系到我们这个问题坑比较深的层次。
iOS7:UITableView中存在n+1个UIScrollView,一个是UITableView本身,另外n个存在于UITableViewCell与cell的contentView之间,类名为UITableViewCellScrollView,活的不久,仅存在于iOS7中,在iOS8中已被移除。
iOS8:UITableView中存在2个UIScrollView,一个是UITableView本身,另外一个存在于UITableView与UITableViewCell之间,类名为UITableViewWrapperView。需要注意的是,UITableViewWrapperView在iOS7中并不是一个UIScrollView。

科普知识完,那么我们就有了以下的问题解决方案了:
1、将UIButton所有属于UIScrollView的父视图的delaysContentTouches属性设置成为NO。
2、继承UIScrollView或UITableView,并重写- (BOOL)touchesShouldCancelInContentView:(UIView*)view方法,让其响应拖动方法。

以下是参考代码:
为了简便我将两个类的子类写在同一个文件中
NoDelayButtonScrollView.h:

#import <UIKit/UIKit.h> @interface NoDelayButtonScrollView : UIScrollView @end @interface NoDelayButtonTableView : UITableView @end
NoDelayButtonScrollView.m(1):

#import "NoDelayButtonScrollView.h" @implementation NoDelayButtonScrollView - (id)initWithCoder:(NSCoder *)aDecoder { self = [super initWithCoder:aDecoder]; if (self) { self.delaysContentTouches = NO; } return self; } - (BOOL)touchesShouldCancelInContentView:(UIView *)view { if ([view isKindOfClass:[UIButton class]]) { return YES; } return [super touchesShouldCancelInContentView:view]; } @end
NoDelayButtonScrollView.m(2):

@implementation NoDelayButtonTableView - (id)initWithCoder:(NSCoder *)aDecoder { self = [super initWithCoder:aDecoder]; if (self) { self.delaysContentTouches = NO; // iterate over all the UITableView's subviews for (id view in self.subviews) { // looking for a UITableViewWrapperView if ([NSStringFromClass([view class]) isEqualToString:@"UITableViewWrapperView"]) { // this test is necessary for safety and because a "UITableViewWrapperView" is NOT a UIScrollView in iOS7 if([view isKindOfClass:[UIScrollView class]]) { // turn OFF delaysContentTouches in the hidden subview UIScrollView *scroll = (UIScrollView *) view; scroll.delaysContentTouches = NO; } break; } } } return self; } - (BOOL)touchesShouldCancelInContentView:(UIView *)view { if ([view isKindOfClass:[UIButton class]]) { return YES; } return [super touchesShouldCancelInContentView:view]; } @end
以上分别对UIScrollView和UITableView进行继承,重写initWithCoder:方法可保证使用Nib文件也能生效
使用这两个类继承写出来的ScrollView和TableView都能快速响应子Button的TouchDown事件,并显示高亮
但以上代码仍未能解决iOS7下UITableView的子Button高亮延迟问题。

可加入以下代码来解决:

for (id obj in cell.subviews) { if ([NSStringFromClass([obj class]) isEqualToString:@"UITableViewCellScrollView"]) { UIScrollView *scroll = (UIScrollView *) obj; scroll.delaysContentTouches = NO; break; } }
这段代码可加在Custom的UITableViewCell的initWithCoder:方法中,也可以放在UITableViewDelegate的cellForRowAtIndexPath:方法中设置对应cell中的UITableViewCellScrollView。

以上,是所有帮助你解决Button延迟高亮问题的方法。


[iOS] UIButton 不响应或延迟响应 UIControlEventTouchDown 事件的解决办法

UIControlEventTouchDown即按钮按下时应触发的方法。实际使用过程中会出现延迟响应或间歇无响应,但是放开手指时会直接响应UIControlEventTouchDown、UIContr...
  • zyb050607
  • zyb050607
  • 2014年12月22日 14:42
  • 4315

UIButton 不响应或延迟响应 UIControlEventTouchDown

UIControlEventTouchDown使用过程中会出现延迟响应或间歇无响应,一直响应特别的慢,一开始以为是程序哪里写错了,最终发现程序没有问题、就上网找些程序员们解答,最终解决问题,在此在此记...
  • zhangjunjian127
  • zhangjunjian127
  • 2015年04月07日 20:30
  • 4574

iOS7/8 UIButton高亮状态延迟有关问题全解

iOS7/8 UIButton高亮状态延迟问题全解 估计很多码友都遇到过这样的情况: UIButton在某些情况下不能立刻响应TouchDown事件,换句话说,迅速点击按钮时,你是永远...
  • hyugahinat
  • hyugahinat
  • 2015年05月31日 21:05
  • 4618

UIButton 点击事件响应延迟 问题解决

UIButton 点击事件响应延迟 问题解决 问题表现 我在UITableView的Header上添加了一个视图(FiltersView),FiltersView上面添加了不定数量的 UIButt...
  • zzsatym
  • zzsatym
  • 2016年07月07日 11:25
  • 2385

UIButton 不响应或延迟响应 UIControlEventTouchDown 事件的解决办法

UIControlEventTouchDown即按钮按下时应触发的方法。实际使用过程中会出现延迟响应或间歇无响应,但是放开手指时会直接响应UIControlEventTouchDown、UIContr...
  • YUXIANG19876021
  • YUXIANG19876021
  • 2015年09月16日 09:43
  • 888

UITouch事件不响应的解决方案

在开发中遇到了这样一个问题:为什么我写的touchesBegan方法没有执行呢?怎么解决呢? 我查找了一下原因:UI Scroll View拦截了UI View的事件。解决办法就是让事件传递过去。具体...
  • City_Night
  • City_Night
  • 2015年03月17日 16:45
  • 530

UIButton点击不灵敏的问题.

要检查按钮是否加在了UIImageView上,如果是那就是这个的问题.因为它的UserInteraction属性默认是设为NO的。 解决办法. 要设置它为YES. 例如原来你是 UIButto...
  • sanjunsheng
  • sanjunsheng
  • 2015年01月28日 20:44
  • 3398

iOS里延迟的执行和取消

最近在项目中遇到了一个需要延迟执行的需求,出于习惯选择了GCD的dispatch_after这个函数。但由于项目需要某个场景下取消这个处于等待执行中的action, 当时没有找到对于的方法,就换成了p...
  • u013749108
  • u013749108
  • 2016年04月08日 00:29
  • 4402

iOS延迟调用和取消延迟调用

iOS开发延迟调用,系统提供了二种方法。 1. performSelector这二个方法是延迟调用的方法。 cancel是取消延迟调用的方法。 具体用法详解: 注意:取消延迟调用时,...
  • Carson_zj
  • Carson_zj
  • 2016年11月05日 09:40
  • 1164

IOS-不响应旋转事件

当一个UIWindow里面加入多个UIViewController时,只有第一个加入到UIWindow的对象能响应旋转事件...
  • ch_soft
  • ch_soft
  • 2012年03月23日 14:53
  • 1608
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:iOS UIButton在某些情况下不能立刻响应TouchDown事件
举报原因:
原因补充:

(最多只允许输入30个字)