uiscrollview的touch事件 以及上面子视图touch事件 实现原理

我们知道当多个视图进行叠加的时候,touch事件是作用到最上面的视图上,但是如果父视图是UIScrollView,如果默认,可能touch子视图会造成UIScrollView的滚动。

UIScrollView滚动的原因,可以看UIScrollView 原理

我在这里简单的描述一下,UIScrollView的工作原理,当手指touch的时候,UIScrollView会拦截Event,会等待一段时间,在这段时间内,如果没有手指没有移动,当时间结束时,UIScrollView会发送tracking events到子视图上。在时间结束前,手指发生了移动,那么UIScrollView就会进行移动,从而取笑发送tracking。

 

那么,UIScrollView的子类想要接受touch事件,就是用户点击UIScrollView上的视图时,要先处理视图上的touch,而不发生滚动。这时候就需要UIScrollView的子类重载touchesShouldBegin:withEvent:inContentView: ,从而决定自己是否接受子视图中的touch事件。

上面都是理论的知识,下面看一个简单的例子:

外面红色是一个UIScrollView,黄色是在UIScrollView上添加的UIView。最后的效果是,当在黄色区域内touch时,touch事件会作用到UIView上,当touch红色区域时,整个视图上下滚动。下面是实现的过程。

一、创建工程,然后创建myScrollView,并且myScrollView继承自UIScrollView。

#import <UIKit/UIKit.h>

   

@interface myScrollView : UIScrollView { 
}

   

@end

具体的实现:

#import "myScrollView.h"

   

#import "MyView.h"

   

@implementation myScrollView

   

- (id)initWithFrame:(CGRect)frame 

    self = [super initWithFrame:frame]; 
    if (self) { 
        [self setBackgroundColor:[UIColor redColor]]; 
        
        MyView *myView=[[MyView alloc] initWithFrame:CGRectMake(1, 3, 100, 200)]; 
        [self addSubview:myView]; 
        [myView release]; 
    } 
    return self; 
}

   

- (void)dealloc 

    [super dealloc]; 
}

   

- (BOOL)touchesShouldBegin:(NSSet *)touches withEvent:(UIEvent *)event inContentView:(UIView *)view 

    NSLog(@"用户点击了scroll上的视图%@,是否开始滚动scroll",view); 
    //返回yes 是不滚动 scroll 返回no 是滚动scroll 
    return YES; 

- (BOOL)touchesShouldCancelInContentView:(UIView *)view 

  
    NSLog(@"用户点击的视图 %@",view); 
   
    //NO scroll不可以滚动 YES scroll可以滚动 
    return NO; 

@end

重写了- (BOOL)touchesShouldBegin:(NSSet *)touches withEvent:(UIEvent *)event inContentView:(UIView *)view方法和- (BOOL)touchesShouldCancelInContentView:(UIView *)view方法。

其中(BOOL)touchesShouldBegin:(NSSet *)touches withEvent:(UIEvent *)event inContentView:(UIView *)view,是用户点击黄色区域内,先触发这个方法,当返回YES时,touch事件作用到黄色视图上,当返回no时,红色可以上下滚动。

(BOOL)touchesShouldCancelInContentView:(UIView *)view是发送tracking前,先作用这个方法。

下面是点击黄的区域的日志:

2011-06-02 10:19:42.469 scrollTouch[38255:207] 用户点击了scroll上的视图<MyView: 0x4e26f90; frame = (1 3; 100 200); layer = <CALayer: 0x4e270a0>>,是否开始滚动scroll 
2011-06-02 10:19:42.658 scrollTouch[38255:207] 用户点击的视图 <MyView: 0x4e26f90; frame = (1 3; 100 200); layer = <CALayer: 0x4e270a0>>

二、添加mySrollView到根视图上:

- (void)viewDidLoad 

    [super viewDidLoad]; 
    
    myScrollView *view=[[myScrollView alloc] initWithFrame:CGRectMake(10, 9, 300, 400)]; 
    [view setUserInteractionEnabled:YES]; 
    [view setScrollEnabled:YES]; 
    
    //NO 发送滚动的通知 但是就算手指移动 scroll也不会动了 YES 发送通知 scroll可以移动 
    [view setCanCancelContentTouches:YES]; 
    [view setBounces:NO]; 
    // NO 立即通知touchesShouldBegin:withEvent:inContentView 看是否滚动 scroll 
    [view setDelaysContentTouches:NO]; // 这句是关键,默认为YES,不设为NO则touchesShouldBegin:withEvent:inContentView:可能不被回调
    [view setContentSize:CGSizeMake(300, 900)]; 
    [self.view addSubview:view]; 
    [view release]; 
}

三、MyView视图的实现。

#import "MyView.h"

   

@implementation MyView

   

- (id)initWithFrame:(CGRect)frame 

    self = [super initWithFrame:frame]; 
    if (self) { 
        [self setBackgroundColor:[UIColor yellowColor]]; 
    } 
    return self; 
}

   

- (void)dealloc 

    [super dealloc]; 
}

   

@end

源代码:http://easymorse-iphone.googlecode.com/svn/trunk/scrollTouch/






通过监听手指点击的位置来判断点击的是哪一个scrollview来进行处理

首先自定义一个scrollview在里面重载以下方法

 

- (BOOL)touchesShouldBegin:(NSSet *)touches withEvent:(UIEvent *)event inContentView:(UIView *)view
{
    // 获取一个UITouch
    UITouch *touch = [touches anyObject];
    // 获取当前的位置
    CGPoint current = [touch locationInView:self];
    CGFloat y = 280;
    if (current.y >= y+ 10) {
        //在地图上
        NSLog(@"滚动地图");
        return YES;
    } else {
        return [super touchesShouldBegin:touches withEvent:event inContentView:view];
    }
}

touchesShouldCancelInContentView从字面理解大概意思为 应该取消当前视图的触摸事件
- (BOOL)touchesShouldCancelInContentView:(UIView *)view
{
    if ([view isKindOfClass:NSClassFromString(@"TapDetectingView")]) {

//在地图上返回NO
        return NO;
    } else {
        return [super touchesShouldCancelInContentView:view];
    }
}
self.delaysContentTouches = NO;

当手指放到UIScrollview上时,uiscrollview会等待一个时间段才去响应触摸事件,这个属性关闭后无论手指移动的多么快都可以直接响应事件



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值