当前位置:   article > 正文

iOS7/8 UIButton高亮状态延迟问题全解_uibutton delayscontenttouches

uibutton delayscontenttouches

估计很多码友都遇到过这样的情况:

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:

  1. #import <UIKit/UIKit.h>
  2. @interface NoDelayButtonScrollView : UIScrollView
  3. @end
  4. @interface NoDelayButtonTableView : UITableView
  5. @end

NoDelayButtonScrollView.m(1):

  1. #import "NoDelayButtonScrollView.h"
  2. @implementation NoDelayButtonScrollView
  3. - (id)initWithCoder:(NSCoder *)aDecoder
  4. {
  5. self = [super initWithCoder:aDecoder];
  6. if (self)
  7. {
  8. self.delaysContentTouches = NO;
  9. }
  10. return self;
  11. }
  12. - (BOOL)touchesShouldCancelInContentView:(UIView *)view
  13. {
  14. if ([view isKindOfClass:[UIButton class]])
  15. {
  16. return YES;
  17. }
  18. return [super touchesShouldCancelInContentView:view];
  19. }
  20. @end

NoDelayButtonScrollView.m(2):

  1. @implementation NoDelayButtonTableView
  2. - (id)initWithCoder:(NSCoder *)aDecoder
  3. {
  4. self = [super initWithCoder:aDecoder];
  5. if (self)
  6. {
  7. self.delaysContentTouches = NO;
  8. // iterate over all the UITableView's subviews
  9. for (id view in self.subviews)
  10. {
  11. // looking for a UITableViewWrapperView
  12. if ([NSStringFromClass([view class]) isEqualToString:@"UITableViewWrapperView"])
  13. {
  14. // this test is necessary for safety and because a "UITableViewWrapperView" is NOT a UIScrollView in iOS7
  15. if([view isKindOfClass:[UIScrollView class]])
  16. {
  17. // turn OFF delaysContentTouches in the hidden subview
  18. UIScrollView *scroll = (UIScrollView *) view;
  19. scroll.delaysContentTouches = NO;
  20. }
  21. break;
  22. }
  23. }
  24. }
  25. return self;
  26. }
  27. - (BOOL)touchesShouldCancelInContentView:(UIView *)view
  28. {
  29. if ([view isKindOfClass:[UIButton class]])
  30. {
  31. return YES;
  32. }
  33. return [super touchesShouldCancelInContentView:view];
  34. }
  35. @end

以上分别对UIScrollView和UITableView进行继承,重写initWithCoder:方法可保证使用Nib文件也能生效
使用这两个类继承写出来的ScrollView和TableView都能快速响应子Button的TouchDown事件,并显示高亮
但以上代码仍未能解决iOS7下UITableView的子Button高亮延迟问题。


可加入以下代码来解决:

  1. for (id obj in cell.subviews)
  2. {
  3. if ([NSStringFromClass([obj class]) isEqualToString:@"UITableViewCellScrollView"])
  4. {
  5. UIScrollView *scroll = (UIScrollView *) obj;
  6. scroll.delaysContentTouches = NO;
  7. break;
  8. }
  9. }

这段代码可加在Custom的UITableViewCell的initWithCoder:方法中,也可以放在UITableViewDelegate的cellForRowAtIndexPath:方法中设置对应cell中的UITableViewCellScrollView。


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



声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/blog/article/detail/93625
推荐阅读
相关标签
  

闽ICP备14008679号