UIScrollView的作用原理,实现scrollView传递touch事件给子视图

2023-05-16

我们知道当多个视图进行叠加的时候,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






本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

UIScrollView的作用原理,实现scrollView传递touch事件给子视图 的相关文章

  • 以编程方式滚动 UIScrollView

    我有一个UIScrollView其中有几个观点 当用户轻弹手指时 视图会根据手指轻弹的方向向右或向左滚动 基本上我的代码的工作方式与 iPhone 照片应用程序类似 现在 有没有一种方法可以让我以编程方式执行相同的操作 以便我最终得到一个通
  • 如何获取 UIScrollView 中的当前缩放级别?

    为了尝试创建一种解决方法 使图像在 UIScrollView 中居中并使其表现得像 Apple 的照片应用程序一样 我需要获取当前的缩放级别并使用该数字来计算图像在每个缩放级别应插入的量 注意 我知道一些程序员通过将图像集中在与滚动视图大小
  • UIACollectionView 单元格与visibleCells

    我正在尝试使用 xcode 4 5 中的自动化编写测试脚本 我有一个UICollectionView我想单击一些当前不可见的单元格 根据文档 http developer apple com library ios documentatio
  • Android MotionEvent.ACTION_MASK

    在 OnTouchEvent 中 如果您使用以下命令切换不同的触摸操作 switch e getAction 它处理 ACTION DOWN 和 ACTION MOVE 但由于某种原因它不会捕获 ACTION POINTER DOWN 而如
  • ScrollView 中的 ViewPager

    我需要有一个ViewPager里面一个ScrollView but ViewPager只是在进入时不会出现ScrollView 当我不使用时一切正常ScrollView 我在 stackoverflow 或其他网站上看到了一些类似的问题 所
  • Android 滚动视图在添加文本时自动滚动

    我在 Android 应用程序中有一个包含文本视图的滚动视图 此文本视图将按设定的时间间隔连续附加文本 滚动有效并且文本添加得很好 但我想做的是在添加文本时让滚动视图自动向下滚动 当新文本添加到底部时 它会自动向下滚动以匹配 而旧文本会在顶
  • 如何在滚动更改事件上获取android滚动视图的第一个可见子项

    我想在每个滚动更改事件上从 android 滚动视图获取第一个可见的子视图 就像 当我们向下滚动时 我们会得到所有即将在屏幕上可见的视图 ID 或引用 如何 我自己得到了它 这是我的代码 在这里 我们需要创建自定义回调监听器 在其 onSc
  • 关闭 UIScrollView 中的键盘

    好吧 我有几个UITextFields and UITextViews里面一个UIScrollView 我想将键盘设置为消失scrollview被触摸或滚动 当然 当您触摸文本字段 视图内时除外 我目前的尝试是替换UIScrollView与
  • iOS ScrollView 需要对 y 位置或高度进行约束

    ViewController View ScrollView Top Bottom Leading Trailing spaces to superview set to 0 ContentView Top Bottom Leading T
  • 修复 iPhone/iPad/iPod 上的 CSS 悬停问题

    我想修复 iOS 上的悬停效果 更改为触摸事件 但我不知道 让我解释一下 您的页面中有一段文字 div class mm hello world div 风格 mm color 000 padding 15px mm hover backg
  • Android 滚动视图不会一直向下滚动

    我查看了很多问题 但列出的解决方案都没有解决我的问题 Scrollview 不会滚动到底部边缘 https stackoverflow com questions 17124680 scrollview doesnt scroll to t
  • IBOutlet 未在 awakeFromNib 中连接

    此处链接的示例代码效果很好 允许 UIScrollView 显示分页图像并预览当前图像之前和之后的图像 http blog proculo de archives 180 Paging enabled UIScrollView With P
  • 让 GMSCircle 响应点击?

    我正在使用适用于 iOS 的 Google 地图 API 我希望当您点击 GMSCircle 时 它 会弹出我在其他地方编写的一些小东西 我已将圆圈设置为 可点击 但我找不到需要设置或制作的内容来监听点击 我用什么 CLLocationCo
  • 如何让scrollViewDidScrollToTop 在 UITableView 中工作?

    我认为标题已经说明了一切 我希望当用户滚动到表格视图的顶部时收到通知 我尝试了以下方法 但没有成功 甚至将 UIScrollViewDelegate 添加到 h 文件中 void scrollViewDidScrollToTop UIScr
  • UIScrollView 在 vi​​ewwillappear 中设置 contentoffset 不起作用

    我想知道是否可以在 viewwillappear 方法中为 uiscrollview 设置 contentoffset void viewWillAppear BOOL animated self scrollView setContent
  • 在 Android 中向下滚动列表视图时强制关闭

    当我尝试在片段活动中向下滚动列表视图时 出现强制关闭错误 其中有 1 个图像视图和 2 个文本视图 我是android的初学者 所以除了android最常用组件的基本场景之外没有太多的知识 没有位图 OOM 错误 因为我也没有使用图像进行了
  • 是否包括触摸事件客户端X/Y 滚动?

    我正在尝试获取相对于的触摸坐标viewport来自触摸事件的浏览器 例如触摸启动 我尝试从 clientX Y 属性获取它们 但两者实际上都返回包括滚动在内的值 这是违反规范的 因为它说 clientX Y 应该返回坐标而不滚动 我尝试添加
  • iOS:UIScrollView 检测滑动手势

    我有一个 UIScrollView 它通过使用计时器自动滚动 每 3 秒滚动到下一页 类似于幻灯片 现在我想实现一个检测任何用户交互的函数 一旦用户与滚动视图交互就取消计时器 以便他可以自己滚动滚动视图 最好的方法是什么 ScrollVie
  • 将 UIImageView 置于 UIScrollView 内而不使用 contentInset?

    我一直无法找到我遇到的这个问题的答案 我在 UIScrollView 中有一个 UIImageView 我希望将其内容垂直居中 目前 我能够做到这一点的唯一方法是根据 UIImageView 大小的高度设置滚动视图的 contentInse
  • 防止UIScrollView的UIPanGestureRecognizer遮挡UIScreenEdgePanGestureRecognizer

    我有一个UIScrollView它填满了我应用程序的一页上的屏幕 但我希望允许用户从屏幕边缘平移以显示其后面的视图 问题是 UIScrollView 窃取了我的触摸UIScreenEdgePanGestureRecognizer在屏幕边缘

随机推荐