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

相关推荐
sweet丶14 小时前
iOS 蓝牙开发深入总结
ios·蓝牙
Digitally17 小时前
免费将 iPhone 音乐传输到电脑:6 种方法
ios·iphone
带娃的IT创业者18 小时前
MLX-VLM:在Mac上解锁视觉语言模型的本地推理与微调能力
人工智能·macos·语言模型·mac·视觉语言模型·mlx·本地推理
Nan-h118 小时前
Omi 录屏专家点击缩放是什么?录制、编辑、预览、导出流程说明
macos
一个人旅程~18 小时前
使用OpenCore-Patcher解决Monterey 蓝牙故障处理完整使用方法及卸载回退指导书
经验分享·macos·电脑
黄毛火烧雪下19 小时前
Mac 上用 Charles 抓取 iPhone 的 HTTPS 请求
网络协议·macos·https
_柒安1 天前
macsvn:Mac 上的 SVN 客户端工具介绍
macos·svn
kevinli1 天前
帮Apple修Bug
ios·llvm
2501_915921431 天前
Xcode与iOS SDK完整教程:从下载安装到配置优化全解析
ide·vscode·ios·objective-c·个人开发·swift·敏捷流程
zandy10111 天前
Hermes Agent 完全安装指南(Linux、macOS、Windows、Android)
linux·windows·macos·agent·安装指南