iOS开发 事件响应链应用

一、通过视图找到控制器

  1. 封装分类UIView+ViewController.h
# import "UIView+ViewController.h"
@implementation UIView (ViewController)
- (UIViewController *)viewContoller {
  
    UIResponder *next = self.nextResponder;
    do {
        if ([next isKindOfClass:[UIViewController class]]) {
            return (UIViewController *)next;
        }
        next = next.nextResponder;
    } while (next != nil)
    return nil;
}
@end

事件传递链 Appdelegate->UIApplication->UIWindow->UIViewController->UIView-Subviews

二、封装圆形按钮点击button

  1. 通过pointInside方法修改响应范围,去除圆圈之外的范围
#import "FifthButton.h"

@implementation FifthButton

-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event{
    BOOL flag = [super pointInside:point withEvent:event];
    if (flag) {
        //贝塞尔曲线 画出圆的范围
        UIBezierPath *path =[UIBezierPath bezierPathWithOvalInRect:self.bounds];
        //圆的范围是否包含点击点
        if ([path containsPoint:point]) {
            return YES;
        }
        
    }
    
    return NO;
}

@end

  1. 调用
self.view.backgroundColor = [UIColor whiteColor];
    UIButton *buttonA = [UIButton buttonWithType:(UIButtonTypeCustom)];
    buttonA.frame = CGRectMake(90, 200, 90, 90);
    buttonA.tag = 1001;
    buttonA.backgroundColor = [UIColor purpleColor];
    [buttonA addTarget:self action:@selector(buttonAction:) forControlEvents:(UIControlEventTouchUpInside)];
    [self.view addSubview:buttonA];
    buttonA.layer.cornerRadius = 45;
    buttonA.layer.masksToBounds = YES;
  1. 效果图


    效果1

三、扩大button的点击范围

需求扩大44 诚意44以下视图的响应范围

  1. 封装button,修改pointInside方法点击范围
#import "FourthButton.h"

@implementation FourthButton

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event{
    
    CGRect bounds = self.bounds;
    //若原来点击大小大于44*44保持不变,否则增长
    //MAX(A,B)两个值比较,取最大值.注意NSUInteger类型
    // https://www.jianshu.com/p/82a9d1ce8157
    CGFloat width = MAX(44.0-bounds.size.width, 0);
    CGFloat height = MAX(44.0-bounds.size.height, 0);
    bounds = CGRectInset(bounds, -0.5*width, -0.5*height);
    return CGRectContainsPoint(bounds, point);
}


@end

CGRectInset参考

四、子视图超出父视图无法点击

  1. 封装父视图
#import "ThirdButton.h"
@implementation ThirdButton

- (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event {
    UIView * view = [super hitTest:point withEvent:event];
    if (view == nil) {
        for (UIView * subView in self.subviews) {
            // 将父视图坐标系的点转换成子视图坐标系的点
            CGPoint tp = [subView convertPoint:point fromView:self];
            if (CGRectContainsPoint(subView.bounds, tp)) {
                view = subView;
            }
        }
    }
    return view;
}

@end
  1. 调用
 self.view.backgroundColor = [UIColor whiteColor];
    ThirdButton *buttonA = [ThirdButton buttonWithType:(UIButtonTypeCustom)];
    buttonA.frame = CGRectMake(0, 60, 100, 100);
    buttonA.tag = 1001;
    buttonA.backgroundColor = [UIColor redColor];
    [buttonA addTarget:self action:@selector(buttonAction:) forControlEvents:(UIControlEventTouchUpInside)];
    [self.view addSubview:buttonA];
    UIButton *buttonB = [UIButton buttonWithType:(UIButtonTypeCustom)];
    buttonB.frame = CGRectMake(60, 60, 200, 200);
    buttonB.tag = 1002;
    buttonB.alpha = 0.4;
   // buttonB.userInteractionEnabled = NO;
    buttonB.backgroundColor = [UIColor yellowColor];
    [buttonB addTarget:self action:@selector(buttonAction:) forControlEvents:(UIControlEventTouchUpInside)];
    [buttonA addSubview:buttonB];
  1. 效果


    效果2

convertPoint参考链接

五、两个覆盖的button

需求:self.vew先加入按钮A(红色),然后加入按钮B(黄色),黄色覆盖红色,想要点击时候红色按钮红色事件响应,点击黄色黄色按钮响应。

  1. 封装黄色按钮
#import "MyButton.h"


// 使用全局的rect 我们利用extern关键字可以用来访问程序的全局变量;
//注释:这里的全局变量指的是,全程需只有一个的全局变量。

extern CGRect rect;

@implementation MyButton



- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    // 判断点击的点是否在小按钮区域内
    BOOL isContains = CGRectContainsPoint(rect, point);
    if (isContains) {
        return nil;
    }
    return [super hitTest:point withEvent:event];
}


@end

  1. 调用
//
//  SecondViewController.m
//  xiangyinglian
//
//  Created by eport on 2021/1/8.
//

#import "SecondViewController.h"
#import "MyButton.h"


CGRect rect;

@interface SecondViewController ()

@end

@implementation SecondViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    self.view.backgroundColor = [UIColor whiteColor];
    
    UIButton *buttonA = [UIButton buttonWithType:(UIButtonTypeCustom)];
    buttonA.frame = CGRectMake(0, 60, 100, 100);
    buttonA.tag = 1001;
    buttonA.backgroundColor = [UIColor redColor];
    [buttonA addTarget:self action:@selector(buttonAction:) forControlEvents:(UIControlEventTouchUpInside)];
    [self.view addSubview:buttonA];
    
    
    MyButton *buttonB = [MyButton buttonWithType:(UIButtonTypeCustom)];
    buttonB.frame = CGRectMake(0, 40, 414, 300);
    buttonB.tag = 1002;
    buttonB.alpha = 0.4;
   // buttonB.userInteractionEnabled = NO;
    buttonB.backgroundColor = [UIColor yellowColor];
    [buttonB addTarget:self action:@selector(buttonAction:) forControlEvents:(UIControlEventTouchUpInside)];
    [self.view addSubview:buttonB];
    
    
    // 获取button1相对于button2的frame
    
    rect = [buttonA convertRect:buttonA.bounds toView:buttonB];
    
    
}

-(void)buttonAction:(UIButton *)btn{
    if (btn.tag == 1001) {
        NSLog(@"红色按钮响应了");
    }
    else if(btn.tag == 1002){
        
        NSLog(@"黄色按钮响应了");
    }
}


@end

  1. 效果3


    效果3

convertRect参考链接

你可能感兴趣的:(iOS开发 事件响应链应用)