iOS hitTest 机制用处之二-----使用pointInside方法

2024-06-02 08:12

本文主要是介绍iOS hitTest 机制用处之二-----使用pointInside方法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

hittest 机制

下面是伪代码

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{if (self.hidden == NO || self.alpha < 0.05 || self.userInteractionEnabled == NO) {//1.当满足这几个条件时,直接丢弃touch事件,不再向下分发。return nil;}else{if (![self pointInside:point withEvent:event]) {//2.如果点击point在视图之外,丢弃return nil;}else{//3.分发给子视图if (self.subviews.count > 0) {for (UIView *subView in self.subviews) {UIView *hitTestSubView = [subView hitTest:point withEvent:event];return hitTestSubView;}}else{return self;}}}
}

由上面的hittest机制可以知道,如果我们想扩大一个视图的点击范围,或者让一个超出父视图的子视图可以点击,我们既可以通过重写hittest方法实现,即在hittest 方法中去掉pointinside方法的判断,同时也可以通过重写pointinside 方法来实现
重写任何一个方法都可以实现这两种功能
以前写过通过hittest方法来实现的文章 点击这里
所以这里我们只介绍通过重写pointinside 方法分别实现扩大点击范围和超出父视图可以点击
其实不管是重写hittest 或者是 重写point inside ,不管是
扩大点击范围,或者是超出父视图可以点击,本质上都是
修改系统的判断一个点是否在视图的的判断逻辑

重写hittest, 扩大点击范围我们就去掉系统直接掉用pointinside方法,
改为判断扩大后的rect 是否包含point,超出父视图可以点击
我们就直接将point转换为相对于子视图的point,然后让子视图自己掉用hittest, 看是否返回view
代码如下

//
//  LBHittestButton.m
//  TEXT
//
//  Created by mac on 2024/6/1.
//  Copyright © 2024 刘博. All rights reserved.
//#import "LBHittestButton.h"@interface LBHittestButton ()@property (nonatomic, strong) UIButton *subButton;@end@implementation LBHittestButton- (instancetype)initWithFrame:(CGRect)frame
{if (self = [super initWithFrame:frame]) {[self addSubview:self.subButton];}return self;
}- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{CGPoint pointInSubbutton = [self convertPoint:point toView:self.subButton];if ([self.subButton hitTest:pointInSubbutton withEvent:event]) {return [self.subButton hitTest:pointInSubbutton withEvent:event];}CGRect rect = UIEdgeInsetsInsetRect(self.bounds, self.expandEdgeInset);if (CGRectContainsPoint(rect, point)) {return self;}return [super hitTest:point withEvent:event];
}- (void)clickSubButton
{NSLog(@"哈哈哈点击小按钮小按钮");
}#pragma mark - lazy load- (UIButton *)subButton
{if (!_subButton) {_subButton = [UIButton buttonWithType:UIButtonTypeCustom];_subButton.frame = CGRectMake(100, 140, 40, 40);_subButton.backgroundColor = [UIColor redColor];[_subButton addTarget:self action:@selector(clickSubButton) forControlEvents:UIControlEventTouchUpInside];}return _subButton;
}@end

重写point inside ,如果是扩大点击范围,我们就判断新的rect是否包含point, 如果是子视图超出父视图可以点击,我们就将point转换为相对于子视图的point,然后判断是否在子视图中
代码如下

//
//  LBHittestButton.m
//  LBHitTestDemo
//
//  Created by mac on 2024/6/2.
//#import "LBHittestButton.h"@interface LBHittestButton ()@property (nonatomic, strong) UIButton *subButton;@end@implementation LBHittestButton- (instancetype)initWithFrame:(CGRect)frame
{if (self = [super initWithFrame:frame]) {[self addSubview:self.subButton];}return self;
}- (void)subButtonClick
{NSLog(@"点击了子视图");
}- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{CGPoint point2 = [self convertPoint:point toView:self.subButton];if ([self.subButton pointInside:point2 withEvent:event]) {return YES;}CGRect rect2 = UIEdgeInsetsInsetRect(self.bounds, self.expandEdgeInsets);if (CGRectContainsPoint(rect2, point)) {return YES;}return [super pointInside:point withEvent:event];
}#pragma mark - lazy load- (UIButton *)subButton
{if (!_subButton) {_subButton = [UIButton buttonWithType:UIButtonTypeCustom];_subButton.frame = CGRectMake(100, 200, 40, 40);_subButton.backgroundColor = [UIColor cyanColor];[_subButton addTarget:self action:@selector(subButtonClick) forControlEvents:UIControlEventTouchUpInside];}return _subButton;
}@end

demo链接

这篇关于iOS hitTest 机制用处之二-----使用pointInside方法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1023419

相关文章

Feign Client超时时间设置不生效的解决方法

《FeignClient超时时间设置不生效的解决方法》这篇文章主要为大家详细介绍了FeignClient超时时间设置不生效的原因与解决方法,具有一定的的参考价值,希望对大家有一定的帮助... 在使用Feign Client时,可以通过两种方式来设置超时时间:1.针对整个Feign Client设置超时时间

使用Python实现一键隐藏屏幕并锁定输入

《使用Python实现一键隐藏屏幕并锁定输入》本文主要介绍了使用Python编写一个一键隐藏屏幕并锁定输入的黑科技程序,能够在指定热键触发后立即遮挡屏幕,并禁止一切键盘鼠标输入,这样就再也不用担心自己... 目录1. 概述2. 功能亮点3.代码实现4.使用方法5. 展示效果6. 代码优化与拓展7. 总结1.

使用Python开发一个简单的本地图片服务器

《使用Python开发一个简单的本地图片服务器》本文介绍了如何结合wxPython构建的图形用户界面GUI和Python内建的Web服务器功能,在本地网络中搭建一个私人的,即开即用的网页相册,文中的示... 目录项目目标核心技术栈代码深度解析完整代码工作流程主要功能与优势潜在改进与思考运行结果总结你是否曾经

C/C++错误信息处理的常见方法及函数

《C/C++错误信息处理的常见方法及函数》C/C++是两种广泛使用的编程语言,特别是在系统编程、嵌入式开发以及高性能计算领域,:本文主要介绍C/C++错误信息处理的常见方法及函数,文中通过代码介绍... 目录前言1. errno 和 perror()示例:2. strerror()示例:3. perror(

Linux中的计划任务(crontab)使用方式

《Linux中的计划任务(crontab)使用方式》:本文主要介绍Linux中的计划任务(crontab)使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、前言1、linux的起源与发展2、什么是计划任务(crontab)二、crontab基础1、cro

kotlin中const 和val的区别及使用场景分析

《kotlin中const和val的区别及使用场景分析》在Kotlin中,const和val都是用来声明常量的,但它们的使用场景和功能有所不同,下面给大家介绍kotlin中const和val的区别,... 目录kotlin中const 和val的区别1. val:2. const:二 代码示例1 Java

CSS去除a标签的下划线的几种方法

《CSS去除a标签的下划线的几种方法》本文给大家分享在CSS中,去除a标签(超链接)的下划线的几种方法,本文给大家介绍的非常详细,感兴趣的朋友一起看看吧... 在 css 中,去除a标签(超链接)的下划线主要有以下几种方法:使用text-decoration属性通用选择器设置:使用a标签选择器,将tex

C++变换迭代器使用方法小结

《C++变换迭代器使用方法小结》本文主要介绍了C++变换迭代器使用方法小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录1、源码2、代码解析代码解析:transform_iterator1. transform_iterat

C++中std::distance使用方法示例

《C++中std::distance使用方法示例》std::distance是C++标准库中的一个函数,用于计算两个迭代器之间的距离,本文主要介绍了C++中std::distance使用方法示例,具... 目录语法使用方式解释示例输出:其他说明:总结std::distance&n编程bsp;是 C++ 标准

vue使用docxtemplater导出word

《vue使用docxtemplater导出word》docxtemplater是一种邮件合并工具,以编程方式使用并处理条件、循环,并且可以扩展以插入任何内容,下面我们来看看如何使用docxtempl... 目录docxtemplatervue使用docxtemplater导出word安装常用语法 封装导出方