iOS中扩大button响应区域

一、OC版

OC版使用:

[btn be_setEnlargeEdge:5];
[btn be_setEnlargeEdgeWithTop:10 right:5 bottom:5 left:10];

OC版实现:

//
//  UIButton+BEEnlargeEdge.h
//  TKApp
//
//  Created by luopengfei on 2017/1/5.
//  Copyright © 2017年 luopengfei. All rights reserved.
//

#import 

@interface UIButton (BEEnlargeEdge)


/**
 增大点击区域
 @param size 上左下右的增大量
 */
- (void)be_setEnlargeEdge:(CGFloat)size;

/**
 增大点击区域
 @param size 上左下右的增大量
 */
- (void)be_setEnlargeEdgeWithTop:(CGFloat)top right:(CGFloat)right bottom:(CGFloat)bottom left:(CGFloat)left;

@end





//
//  UIButton+BEEnlargeEdge.m
//  TKApp
//
//  Created by luopengfei on 2017/1/5.
//  Copyright © 2017年 luopengfei. All rights reserved.
//

#import "UIButton+BEEnlargeEdge.h"
#import 

@implementation UIButton (BEEnlargeEdge)

static char topNameKey;
static char rightNameKey;
static char bottomNameKey;
static char leftNameKey;

- (void)be_setEnlargeEdge:(CGFloat)size {
    
    objc_setAssociatedObject(self, &topNameKey, [NSNumber numberWithFloat:size], OBJC_ASSOCIATION_COPY_NONATOMIC);
    objc_setAssociatedObject(self, &rightNameKey, [NSNumber numberWithFloat:size], OBJC_ASSOCIATION_COPY_NONATOMIC);
    objc_setAssociatedObject(self, &bottomNameKey, [NSNumber numberWithFloat:size], OBJC_ASSOCIATION_COPY_NONATOMIC);
    objc_setAssociatedObject(self, &leftNameKey, [NSNumber numberWithFloat:size], OBJC_ASSOCIATION_COPY_NONATOMIC);
}

- (void)be_setEnlargeEdgeWithTop:(CGFloat)top right:(CGFloat)right bottom:(CGFloat)bottom left:(CGFloat)left {
    
    objc_setAssociatedObject(self, &topNameKey, [NSNumber numberWithFloat:top], OBJC_ASSOCIATION_COPY_NONATOMIC);
    objc_setAssociatedObject(self, &rightNameKey, [NSNumber numberWithFloat:right], OBJC_ASSOCIATION_COPY_NONATOMIC);
    objc_setAssociatedObject(self, &bottomNameKey, [NSNumber numberWithFloat:bottom], OBJC_ASSOCIATION_COPY_NONATOMIC);
    objc_setAssociatedObject(self, &leftNameKey, [NSNumber numberWithFloat:left], OBJC_ASSOCIATION_COPY_NONATOMIC);
}

- (CGRect)be_enlargedRect {
    
    NSNumber *topEdge = objc_getAssociatedObject(self, &topNameKey);
    NSNumber *rightEdge = objc_getAssociatedObject(self, &rightNameKey);
    NSNumber *bottomEdge = objc_getAssociatedObject(self, &bottomNameKey);
    NSNumber *leftEdge = objc_getAssociatedObject(self, &leftNameKey);
    
    if (topEdge && rightEdge && bottomEdge && leftEdge) {
        return CGRectMake(self.bounds.origin.x - leftEdge.floatValue,
                          self.bounds.origin.y - topEdge.floatValue,
                          self.bounds.size.width + leftEdge.floatValue + rightEdge.floatValue,
                          self.bounds.size.height + topEdge.floatValue + bottomEdge.floatValue);
    } else {
        return self.bounds;
    }
}

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
    
    CGRect rect = [self be_enlargedRect];
    if (CGRectEqualToRect(rect, self.bounds)) {
        return [super pointInside:point withEvent:event];
    }
    return CGRectContainsPoint(rect, point) ? YES : NO;
}

//- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent*)event {
//     
// CGRect rect = [self enlargedRect];
// if (CGRectEqualToRect(rect, self.bounds)) {
//     return [super hitTest:point withEvent:event];
// }
//     return CGRectContainsPoint(rect, point) ? self : nil;
//}


@end

二、swift版

swift版使用:


let btn = BEButton()
xxxx
btn.setEnlargeEdge(5)
btn.setEnlargeEdge(10, 5, 10, 5)

补充:由于BEButton继承UIButton,可以添加特有属性,使用objc_setAssociatedObject和objc_getAssociatedObject进行 关联 有些画蛇添足了。


//
//  BEButton.swift
//  ShuLian
//
//  Created by 骆鹏飞 on 2018/5/4.
//  Copyright © 2018 GXCJ. All rights reserved.
//

import UIKit

class BEButton: UIButton {
    
    let _top = "_top"
    let _left = "_left"
    let _bottom = "_bottom"
    let _right = "_right"
    
    override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
        
        let rect = enlargedRect()
        if rect.equalTo(bounds) {
            return super.point(inside: point, with: event)
        }
        return rect.contains(point) ? true : false
    }
    
}

extension BEButton {
    
    func setEnlargeEdge(_ length:Float) {
        
        setEnlargeEdge(length, length, length, length)
    }
    
    func setEnlargeEdge(_ top:Float, _ left:Float, _ bottom:Float, _ right:Float) {
        
        objc_setAssociatedObject(
            self,
            UnsafeRawPointer(bitPattern: _top.hashValue)!,
            NSNumber(value: top),
            .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        objc_setAssociatedObject(
            self,
            UnsafeRawPointer(bitPattern: _left.hashValue)!,
            NSNumber(value: left),
            .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        objc_setAssociatedObject(
            self,
            UnsafeRawPointer(bitPattern: _bottom.hashValue)!,
            NSNumber(value: bottom),
            .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        objc_setAssociatedObject(
            self,
            UnsafeRawPointer(bitPattern: _right.hashValue)!,
            NSNumber(value: right),
            .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
    }
    
    private func enlargedRect() -> CGRect {

        let topEdge = objc_getAssociatedObject(self, UnsafeRawPointer(bitPattern: _top.hashValue)!) as? NSNumber
        let rightEdge = objc_getAssociatedObject(self, UnsafeRawPointer(bitPattern: _left.hashValue)!) as? NSNumber
        let bottomEdge = objc_getAssociatedObject(self, UnsafeRawPointer(bitPattern: _bottom.hashValue)!) as? NSNumber
        let leftEdge = objc_getAssociatedObject(self, UnsafeRawPointer(bitPattern: _right.hashValue)!) as? NSNumber
        
        if ((topEdge != nil) && (leftEdge != nil) && (bottomEdge != nil) && (rightEdge != nil)) {
            
            return CGRect(
                x: bounds.origin.x - CGFloat(leftEdge!.floatValue),
                y: bounds.origin.y - CGFloat(topEdge!.floatValue),
                width: bounds.width + CGFloat(leftEdge!.floatValue) + CGFloat(rightEdge!.floatValue),
                height: bounds.height + CGFloat(topEdge!.floatValue) + CGFloat(bottomEdge!.floatValue))
            
        } else {
            return self.bounds
        }
    }
}

原理:重写pointInside: withEvent:方法,改变判断点击的区域是否在某个视图中的逻辑。
虽然对UIButton做extension会使用更方便,但无形中会增加许多性能消耗,而且很容易与其他的extension冲突。所以建议写一个专门扩大相应区域的Button类,类似BEButton,有需要时就使用。

你可能感兴趣的:(iOS中扩大button响应区域)