UIScrollView的作用原理,实现scrollView传递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事件。

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

image

外面红色是一个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) {
        // Initialization code
        [self setBackgroundColor:[UIColor redColor]];
        
        myView * aView = [[myView alloc] initWithFrame:CGRectMake(1, 3, 100, 200)];
        [self addSubview:aView];
        [aView release];
    }
    return self;
}

- (BOOL)touchesShouldBegin:(NSSet *)touches withEvent:(UIEvent *)event inContentView:(UIView *)view {
    NSLog(@"用户触摸了scroll上的视图%@,是否开始滚动scroll", view);
    //返回yes - 将触摸事件传递给相应的subView; 返回no - 直接滚动scrollView,不传递触摸事件到subView
    return YES// NO;
}

- (BOOL)touchesShouldCancelInContentView:(UIView *)view{
    NSLog(@"scrollView取消传递触摸事件到视图%@", view);    
    //no - 不取消,touch事件由view处理,scrollView不滚动; yes - scrollView取消,touch事件由scrollView处理,可滚动
    return YES// NO;
}

@end

重写了方法

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

- (BOOL)touchesShouldCancelInContentView:(UIView *)view。


(BOOL)touchesShouldBegin:withEvent:inContentView:

用户点击黄色区域时,先触发这个方法。

当返回YES时,touch事件作用到黄色视图上;

当返回no时,touch事件不传递到黄色视图,红色视图马上滚动(当然前提是scrollView的scrollEnabled字段为YES)。


(BOOL)touchesShouldCancelInContentView:

只有scrollView的canCancelContentTouches字段为YES 且 (BOOL)touchesShouldBegin:withEvent:inContentView:返回YES时,这个方法才会被调用。

调用前,由于(BOOL)touchesShouldBegin:withEvent:inContentView:返回YES,scrollView上对应的view会接收到touch事件,因此方法(BOOL)touchesShouldCancelInContentView:被调用前,view可以已经触发了touchesBegan:withEvent:方法甚至是touchesMoved:withEvent:方法,至于view最后会调用touchesEnden:withEvent:还是touchesCanceled:withEvent:取决于(BOOL)touchesShouldCancelInContentView:的返回值

scrollView发送tracking前,调用这个方法。

返回YES时,若scrollView的canCancelContentTouches字段为YES,view会马上调用touchesCanceled:withEvent:,scrollView进行tracking以滚动。

返回NO时,scrollView不进行tracking,也不滚动,touch事件交由view处理。


二、添加mySrollView到根视图上

- (void)viewDidLoad
{
    [super viewDidLoad];
	// Do any additional setup after loading the view, typically from a nib.    
    [self layoutCstmView];
}

- (void)layoutCstmView
{
    myScrollView * scrollView = [[myScrollView alloc] initWithFrame:CGRectMake(10, 9, 300, 400)];
    [scrollView setUserInteractionEnabled:YES];
    [scrollView setScrollEnabled:YES];
    
    //NO - 设置scrollView不能取消传递touch事件,此时就算手指若在subView上滑动,scrollView不滚动; YES - 设置scrollView可取消传递touch事件
    [scrollView setCanCancelContentTouches:YES];
    [scrollView setBounces:NO];
    
    //NO - 立即通知touchesShouldBegin:withEvent:inContentView
    [scrollView setDelaysContentTouches:NO];
    [scrollView setContentSize:CGSizeMake(scrollView.frame.size.width, 900)];
    
    [self.view addSubview:scrollView];
    [scrollView release];
}

三、MyView视图的实现

#import "myView.h"

@implementation myView

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
        self.backgroundColor = [UIColor yellowColor];
    }
    return self;
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    printf("myView touchesBegan \n");
    self.backgroundColor = [UIColor grayColor];
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    printf("myView touchesMoved \n");
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    printf("myView touchesEnded \n");
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
    printf("myView touchesCancelled \n");
    self.backgroundColor = [UIColor yellowColor];
}
   
@end






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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值