早就想写这篇博客了。。一方面懒,一方面杂事多。
这篇博客主要是精简一下WWDC上 Advanced ScrollViews and Touch Handling Techniques的内容。看一看也能略知其中讲了什么,当然只有一部分。
1、首先构建一个简单的界面,随机生成一些 颜色及坐标的圆点,当小圆点被点击时,可以产生按钮点击的高亮效果。
#import "ViewController.h"
@implementation ViewController
{
UIView* _canvasView;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
CGRect bounds = self.view.bounds;
_canvasView = [[UIView alloc] initWithFrame:bounds];
_canvasView.backgroundColor = [UIColor darkGrayColor];
[self.view addSubview:_canvasView];
[self addDots:25 toView:self.view];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void) addDots:(NSUInteger)count toView:(UIView *)view
{
for(NSUInteger i = 0;i<count;i++)
{
DotView* dotView = [DotView randomDotView];
[view addSubview:dotView];
}
}
@end
如下图:
2、为view加上scrollview和UIVisualEffectView,关于UIVisualEffectView大家可以去查一下相关资料,挺实用的一个view但是不知效率如何。
_scrollView = [[UIScrollView alloc] initWithFrame:bounds];
[self.view addSubview:_scrollView];
_drawerView = [[UIVisualEffectView alloc]initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]];
_drawerView.frame = CGRectMake(0, 0, bounds.size.width, 650.0);
[_scrollView addSubview:_drawerView];
_scrollView.contentSize = CGSizeMake(bounds.size.width, bounds.size.height + _drawerView.frame.size.height);
3、由于scrollview的添加,因此会发现那些小圆点已无法点击。此时我们可以采用如下方法:
_scrollView.userInteractionEnabled = NO;
[self.view addGestureRecognizer:_scrollView.panGestureRecognizer];
5、现在我们想同时点击scrollview上的小圆点,也想点击view上的小圆点,那么改如何做呢?
首先列出hitTest的实现方法:
-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent*)event
{
if(/*点击的point处于bounds内部*/)
{
for(/*对于每个子view 在相反的层次顺序下依次被访问*/
{
UIView* hitView = /*在子view上递归调用*/
if(hitView != nil)
{
return hitView;
}
}
return self;
}
return nil;
}
基于上面的代码,我们可以大概了解点击事件如何在view及其子view中响应。
那么现在我们得知这个原理,就可以根据此原理来实现我们的目的。
我们继承scrollview重写其中的hitTest方法。
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
UIView* hitView = [super hitTest:point withEvent:event];
if(hitView == self)
{
return nil;
}
return hitView;
}
当hitView为我们的scrollview时,就返回nil,因此不会点击到下面的小圆点。
那么回到viewcontroller去掉_scrollview.userInteractionEnabled = NO;于是就成功达到了我们的目的。
6、若有些小圆点半径特别小难以点击,此时我们需要明白此方法的作用
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event; // default returns YES if point is in bounds
这个方法在hitTest中调用,形式为
if pointInside(point,withEvent:event //此方法即判断点击是否在我们的bounds内
{
for /**/
....
}
那么我们重写该方法。
-(BOOL)pointInside(CGPoint)point withEvent:(UIEvent*)event
{
CGRect bounds = self.bounds;
if _radius < 22.0
{
CGFloat expansion = 22.0 - _radius; //让bounds扩大
bounds = CGRectInset(bounds,-expansion,-expansion);
}
return CGRectContainsPoint(bounds,point);
}
也就是让实际的点击范围扩大,来使那些小面积view更加易于点击。