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链接

相关推荐
凄凄迷人16 分钟前
如何调试 chrome 崩溃日志(MAC)
前端·chrome·macos·crash
钢门狂鸭20 分钟前
mvn-mac操作小记
macos·maven
疯狂的沙粒22 分钟前
mac 安装node提示 nvm install v14.21.3 failed可能存在问题
macos
赶路人儿23 分钟前
IntelliJ IDEA配置(mac版本)
java·macos·intellij-idea
木有会24 分钟前
【mac】mac自动定时开关机和其他常用命令,管理电源设置的工具pmset
macos
木有会2 小时前
【mac】终端左边太长处理,自定义显示名称(terminal路径显示特别长)
macos
_im.m.z2 小时前
Mac配置和启动 Tomcat
java·macos·tomcat·ssm框架
丁总学Java2 小时前
在 Mac(ARM 架构)上安装 JDK 8 环境
arm开发·macos·架构
koko爱英语3 小时前
Jmeter测试工具的安装和使用,mac版本,jmeter版本5.2.1
测试工具·jmeter·macos
菜鸟小贤贤3 小时前
pyhton+yaml+pytest+allure框架封装-全局变量渲染
python·macos·pytest·接口自动化·jinja2