【转】UIButton 在 UIScrollView 中的 高亮延迟 和 滑动冲突
2015-02-09 11:10
288 查看
最近做项目遇见一个问题:UIScrollView上有许多UIButton,要实现既能点击UIButton,又能滑动UIScrollView,这个实现没有问题,不需要做额外的touch管理,UIScrollView能识别是点击的UIButton还是滑动本身,但是有一个效果上的问题,就是点击UIButton时间短的话,不会高亮,但是确实是触发点击了,这样就造成了假象,给人一种UIButton没有被点击的感觉。如果点击时间长的话没有问题,会高亮。
这么看来,导致这样现象应该就是时间长短的问题,顺着这个问题想下去,就追寻到UIScrollView的touch原理,当UIScrollView接收到一个touch时,它会在一段时间(好像是150ms)内监听该touch是否移动了,假如移动了(应该有一个移动范围),则取消将touch发送到其子视图(例如UIButton),UIScrollView自身接受该touch,进行滑动。看来应该就是这段判断时间惹的祸了(这里其实我还想不明白为什么明明点击了Button,也确实触发了点击,却没有高亮状态,哪位大神知道的话请指教),那要解决问题是不是就应该把这段时间取消掉呢,不要这个判断时间,那么UIButton应该就会立即响应并产生高亮状态吧。正好UIScrollView中有一个属性叫delaysContentTouches,官方文档对它的解释是:If
the value of this property is YES, the scroll view delays handling the touch-down gesture until it can determine if scrolling is the intent. If the value is NO , the scroll view immediately calls touchesShouldBegin:withEvent:inContentView:. The default value
is YES.意思就是设置为NO就不会存在那个150ms的判断时间了,直接执行后续操作。那么咱们设置为NO来试试呗。结果确实如所想那样,UIButton立即响应并高亮。
但是…..别高兴太早,虽然这个问题解决了,但是新的麻烦又产生了,螳螂捕蝉黄雀在后!你会发现UIScrollView滑动不像以前那样了,假如touch down的那点落在UIButton上然后再滑动手指,UIScrollView不会滑动,但是UIButton仍然触发,当然,这样的结果也是应该的,你想想,设置delaysContentTouches为NO后,只要手指点在UIButton上,UIScrollView就会立即判定为这是点击UIButton,而不会再等待看手指是否移动来决定是否要滑动本身了。
那么如何解决这个问题呢?你会想,有没有什么方法可以在touch到UIbutton上并滑动时不触发UIButton而让UIScrollView自己滑动呢,强大的iOS没有让你失望,UIScrollView中有一个方法:touchesShouldCancelInContentView:,来看它的解释:The
scroll view calls this method just after it starts sending tracking messages to the content view. If it receives NO from this method, it stops dragging and forwards the touch events to the content subview. The scroll view does not call this method if the value
of the canCancelContentTouches property is NO.意思就是当UIScrollView将touch事件交给子view后,当手指发生滑动时,调用此方法,假如返回NO,则将touch事件交给子view,如果返回YES,则交给UIScrollView处理,产生滑动。(但是前提是UIScrollView的canCancelContentTouches属性是YES才会调用这个方法,只要不是UIControll的子类,这个属性默认是YES。)所以只要重写UIScrollView的这个方法并返回YES就可以啦,到此问题就解决了。既能立即响应UIButton,也能自由滑动UIScrollView。
举例:
首先定义一个继承UIScrollView的View。
fsScrollView.h
重写touchesShouldCancelInContentView:
fsScrollView.m
然后在需要创建UIScrollView的ViewController中定义ScrollView
.h文件
.m文件
有需要的同学借鉴一下吧。
摘录:
http://blog.sina.com.cn/s/blog_71715bf80101ie1e.html http://www.cocoachina.com/bbs/read.php?tid=234183
这么看来,导致这样现象应该就是时间长短的问题,顺着这个问题想下去,就追寻到UIScrollView的touch原理,当UIScrollView接收到一个touch时,它会在一段时间(好像是150ms)内监听该touch是否移动了,假如移动了(应该有一个移动范围),则取消将touch发送到其子视图(例如UIButton),UIScrollView自身接受该touch,进行滑动。看来应该就是这段判断时间惹的祸了(这里其实我还想不明白为什么明明点击了Button,也确实触发了点击,却没有高亮状态,哪位大神知道的话请指教),那要解决问题是不是就应该把这段时间取消掉呢,不要这个判断时间,那么UIButton应该就会立即响应并产生高亮状态吧。正好UIScrollView中有一个属性叫delaysContentTouches,官方文档对它的解释是:If
the value of this property is YES, the scroll view delays handling the touch-down gesture until it can determine if scrolling is the intent. If the value is NO , the scroll view immediately calls touchesShouldBegin:withEvent:inContentView:. The default value
is YES.意思就是设置为NO就不会存在那个150ms的判断时间了,直接执行后续操作。那么咱们设置为NO来试试呗。结果确实如所想那样,UIButton立即响应并高亮。
但是…..别高兴太早,虽然这个问题解决了,但是新的麻烦又产生了,螳螂捕蝉黄雀在后!你会发现UIScrollView滑动不像以前那样了,假如touch down的那点落在UIButton上然后再滑动手指,UIScrollView不会滑动,但是UIButton仍然触发,当然,这样的结果也是应该的,你想想,设置delaysContentTouches为NO后,只要手指点在UIButton上,UIScrollView就会立即判定为这是点击UIButton,而不会再等待看手指是否移动来决定是否要滑动本身了。
那么如何解决这个问题呢?你会想,有没有什么方法可以在touch到UIbutton上并滑动时不触发UIButton而让UIScrollView自己滑动呢,强大的iOS没有让你失望,UIScrollView中有一个方法:touchesShouldCancelInContentView:,来看它的解释:The
scroll view calls this method just after it starts sending tracking messages to the content view. If it receives NO from this method, it stops dragging and forwards the touch events to the content subview. The scroll view does not call this method if the value
of the canCancelContentTouches property is NO.意思就是当UIScrollView将touch事件交给子view后,当手指发生滑动时,调用此方法,假如返回NO,则将touch事件交给子view,如果返回YES,则交给UIScrollView处理,产生滑动。(但是前提是UIScrollView的canCancelContentTouches属性是YES才会调用这个方法,只要不是UIControll的子类,这个属性默认是YES。)所以只要重写UIScrollView的这个方法并返回YES就可以啦,到此问题就解决了。既能立即响应UIButton,也能自由滑动UIScrollView。
举例:
首先定义一个继承UIScrollView的View。
fsScrollView.h
复制代码 // // fsScrollView.h // mbaby // // Created by fanpingyang on 14-10-13. // Copyright (c) 2014年 moogeek. All rights reserved. // #import <UIKit/UIKit.h> @interface fsScrollView : UIScrollView <UIScrollViewDelegate> @end |
fsScrollView.m
复制代码 // // fsScrollView.m // mbaby // // Created by fanpingyang on 14-10-13. // Copyright (c) 2014年 moogeek. All rights reserved. // #import "fsScrollView.h" @implementation fsScrollView - (BOOL)touchesShouldCancelInContentView:(UIView *)view { //NO scroll不可以滚动 YES scroll可以滚动 return YES; } @end |
.h文件
复制代码 #import <UIKit/UIKit.h> #import "fsScrollView.h" @interface fsSelectViewController : UIViewController<UIScrollViewDelegate> { NSMutableArray *classArray; fsScrollView *classScrollView; } @property(nonatomic,strong) NSMutableArray *classArray; @property(nonatomic,strong) fsScrollView *classScrollView; @end |
复制代码 - (void)viewDidLoad { [super viewDidLoad]; //初始化 辅食分类 [self initClassArray]; classScrollView=[[fsScrollView alloc] initWithFrame:CGRectMake(0,0,classCenterView.bounds.size.width,classCenterView.bounds.size.height) ]; classScrollView.delegate = self; classScrollView.backgroundColor = [UIColor clearColor]; classScrollView.pagingEnabled = NO; classScrollView.showsHorizontalScrollIndicator = NO; classScrollView.showsVerticalScrollIndicator = NO; classScrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth; classScrollView.userInteractionEnabled=YES; [classScrollView setContentOffset:CGPointMake(0, 0)]; classCurrentPage = 0; classPageControl=[[UIPageControl alloc]initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 0)]; classPageControl.numberOfPages = [classArray count]; classPageControl.currentPage = 0; classPageControl.backgroundColor = [UIColor whiteColor]; [self initClassScrollView]; } -(void) initClassArray { classArray=[[NSMutableArray alloc] init]; [classArray addObject:@"粥类"]; [classArray addObject:@"果蔬"]; [classArray addObject:@"蛋类"]; [classArray addObject:@"汤类"]; [classArray addObject:@"糕点"]; [classArray addObject:@"其他"]; [classArray addObject:@"其他"]; [classArray addObject:@"其他"]; [classArray addObject:@"其他"]; [classArray addObject:@"其他"]; } -(void) initClassScrollView { for (int i=0; i<[classArray count]; i++) { UILabel *lblTitle=[[UILabel alloc] initWithFrame:CGRectMake(i*48+2, 0, 48, 34)]; [lblTitle setText:[classArray objectAtIndex:i]]; [lblTitle setTextColor:[UIColor colorWithRed:23.0f/255.0f green:23.0f/255.0f blue:23.0f/255.0f alpha:1.0] ]; [lblTitle setTextAlignment:NSTextAlignmentCenter]; [lblTitle setFont:[UIFont systemFontOfSize:13.0f]]; UIButton *btnItem=[[UIButton alloc] initWithFrame:CGRectMake(i*48+2, 0, 48, 34)]; [btnItem setBackgroundColor:[UIColor clearColor]]; [btnItem setTitle:@"" forState:UIControlStateNormal]; btnItem.tag=[[NSString stringWithFormat:@"1000%d",i] intValue]; [btnItem addTarget:self action:@selector(classItemClickListener:) forControlEvents:UIControlEventTouchUpInside]; btnItem.userInteractionEnabled=YES; [classScrollView addSubview:lblTitle]; [classScrollView addSubview:btnItem]; //[self adjustScrollViewContentX:btnItem]; } classScrollView.contentSize = CGSizeMake(48 * [classArray count], classScrollView.frame.size.height); } -(void) classItemClickListener:(UIButton *)button { int itemIndex=0; NSString *buttonTagStr=[NSString stringWithFormat:@"%d",button.tag]; itemIndex=[[buttonTagStr substringFromIndex:4] intValue]; NSLog(@"click item num: %d",itemIndex); } |
摘录:
http://blog.sina.com.cn/s/blog_71715bf80101ie1e.html http://www.cocoachina.com/bbs/read.php?tid=234183
相关文章推荐
- [解决方案]处理UIScrollView滑动与左右侧栏UIPanGestureRecognizer手势冲突
- iOS UIScrollView左右滑动手势与返回手势冲突的解决办法
- 优化——UIScrollView通过内容延迟加载以达到平滑滑动。
- 解决UIScrollView和滑动返回手势的冲突
- UIScrollView滑动与UITableView左滑删除冲突问题解决方案
- 如何解决UIScrollView中添加UITapGestureRecognizer跟UIButton点击事件冲突
- UIGestureRecognizerDelegate两三事 & UIScrollView滑动 子View上UIPanGestureRecognizer手势冲突
- UIScrollView滑动与轻扫手势冲突
- 解决UIScrollView和滑动返回手势的冲突
- UITableView或UIScrollVIew上的UIButton的高亮效果
- uiscrollview_和_滑动返回冲突解决
- IOS 高仿boss直聘---优雅使用UIButton与UIScrollView打造滑动标签
- 3D轮播图与外层ViewPager滑动冲突问题
- Swift - 调整UIScrollView的滑动速度(适用于tableView、collectionView)
- 《Android View 的事件分发和滑动冲突》 —预习资料
- Android ViewPager和SlidingPaneLayout的滑动事件冲突处理方法
- ViewGrop 滑动与 子View点击事件冲突解决办法
- android控件-ScrollView 和WebView之见滑动冲突解决
- Android中ScrollView与MapView滑动事件冲突解决
- 完美解决SwipeRefreshLayout与RecyclerView滑动冲突问题