scrollview 和 touch handling

来源:互联网 发布:葫芦线切割3b编程实例 编辑:程序博客网 时间:2024/06/05 19:04

早就想写这篇博客了。。一方面懒,一方面杂事多。


这篇博客主要是精简一下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];


4、我们现在给UIVisualEffectView加上小圆点,由于_scrollview.userInteractionEnabled = NO; 因此UIVisualEffectView上的小圆点无法点击,并且可以越过scrollview直接点击背后的小圆点。



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更加易于点击。



0 0