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

相关推荐
Swift社区1 分钟前
在Swift中实现允许重复的O(1)随机集合
开发语言·ios·swift
爱喝矿泉水的猛男8 分钟前
哪些鼠标不支持Mac mouse fix呢?
macos·计算机外设
初级代码游戏21 小时前
iOS开发 SwiftUI 8:NavigationView 导航
ios·swiftui·swift
ASKED_20191 天前
macOS 使用 Codex CLI 登录报错 403 的问题分析与解决方案(Issue #2414)
macos·issue
roo_11 天前
JAVA学习-MAC搭建java环境和spring boot搭建
java·学习·macos
Digitally1 天前
如何在 Mac 上进行屏幕录制(分步教程)
macos
美狐美颜SDK开放平台1 天前
跨平台开发实战:直播美颜sdk动态贴纸在 Android / iOS / HarmonyOS 的落地方案
android·ios·harmonyos·美颜sdk·直播美颜sdk·视频美颜sdk·美颜api
2501_916008891 天前
在不越狱前提下导出 iOS 应用文件的过程,访问应用沙盒目录,获取真实数据
android·macos·ios·小程序·uni-app·cocoa·iphone
2501_915106321 天前
Android和IOS 移动应用App图标生成与使用 Assets.car生成
android·ios·小程序·https·uni-app·iphone·webview
vchao_1 天前
Mac升级系统后反复重启问题
macos·反复重启