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

相关推荐
问道飞鱼35 分钟前
【移动端知识】移动端多 WebView 互访方案:Android、iOS 与鸿蒙实现
android·ios·harmonyos·多webview互访
liliangcsdn1 小时前
smolagents - 如何在mac用agents做简单算术题
人工智能·macos·prompt
mascon2 小时前
U3D打包IOS的自我总结
ios
名字不要太长 像我这样就好2 小时前
【iOS】继承链
macos·ios·cocoa
karshey3 小时前
【IOS webview】IOS13不支持svelte 样式嵌套
ios
潜龙95273 小时前
第4.3节 iOS App生成追溯关系
macos·ios·cocoa
游戏开发爱好者812 小时前
iOS App 电池消耗管理与优化 提升用户体验的完整指南
android·ios·小程序·https·uni-app·iphone·webview
玄辰星君12 小时前
【MAC】nacos 2.5.1容器docker安装
macos·docker·nacos
atwdy17 小时前
MacOS安装linux虚拟机
linux·运维·ubuntu·macos·utm
echola_mendes18 小时前
Dify:在MacOS系统下Dify的本地部署与使用
macos