UIButton 扩大点击范围

引言:

重写一个 Button 类,这个 button 类继承 UIButton ,重写- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent*)event;方法中修改 bounds 的值就可以就可以实现扩大按钮的点击区域。


# 一. 实现方式

自定义一个继承自 UIButton 的 LCScopeButton 类:

# 1. LCScopeButton.h


#import <UIKit/UIKit.h>

@interface LCScopeButton : UIButton

/** 单一方向扩大范围类型 */
typedef enum _LCOneWayScopeType {
	LCOneWayScopeTypeHorizontal = 1, // 水平方向
	LCOneWayScopeTypeVertical = 2, 	// 竖直方向
	LCOneWayScopeTypeTop = 3, 			// 向上扩大
	LCOneWayScopeTypeLeft = 4, 		// 向左扩大
	LCOneWayScopeTypeBottom = 5, 		// 向下扩大
	LCOneWayScopeTypeRight = 6 		// 向右扩大
} LCOneWayScopeType;

/** xy轴双向扩大范围类型 */
typedef enum _LCTwoWayScopeType {
	LCTwoWayScopeTypeAllAround = 1, 	// 四周
	LCTwoWayScopeTypeUPLEFT = 2, 		// 左上
	LCTwoWayScopeTypeLOWERLEFT = 3, 	// 左下
	LCTwoWayScopeTypeUPRIGHT = 4, 	// 右上
	LCTwoWayScopeTypeLOWERRIGHT = 5 	// 右下
} LCTwoWayScopeType;

/**
 * 设置 单一方向的点击范围 scopetype:方向类型 range:扩大或缩小距离
 */
-(void)lc_setOneWayClickScopeWithType:(LCOneWayScopeType)scopetype range:(CGFloat)range;

/**
 * 设置 xy轴的点击范围 rangeX:X轴扩大或缩小距离 rangeY:Y轴扩大或缩小距离
 */
-(void)lc_setTwoWayClickScopeWithType:(LCTwoWayScopeType)scopetype rangeX:(CGFloat)rangeX rangeY:(CGFloat)rangeY;

# 2. LCScopeButton.m


#import "LCScopeButton.h"

@interface LCScopeButton ()

/** 范围 */
@property (nonatomic, assign) CGSize scopeSize;

/** 单一方向扩大范围类型 */
@property (nonatomic, assign) LCOneWayScopeType oneWayscopeType;
/** xy轴双向扩大范围类型 */
@property (nonatomic, assign) LCTwoWayScopeType twoWayscopeType;


@end

@implementation LCScopeButton

/**
 * 设置 单一方向的点击范围 scopetype:方向类型 range:扩大或缩小距离
 */
-(void)lc_setOneWayClickScopeWithType:(LCOneWayScopeType)scopetype range:(CGFloat)range{

	switch (scopetype) {
		case LCOneWayScopeTypeHorizontal: // 水平
			self.scopeSize = CGSizeMake(range, 0);
			self.oneWayscopeType = LCOneWayScopeTypeHorizontal;
		break;

		case LCOneWayScopeTypeVertical: // 竖直
			self.scopeSize = CGSizeMake(0, range);
			self.oneWayscopeType = LCOneWayScopeTypeVertical;
		break;

		case LCOneWayScopeTypeTop: // 向上
			self.scopeSize = CGSizeMake(0, range);
			self.oneWayscopeType = LCOneWayScopeTypeTop;
		break;

		case LCOneWayScopeTypeLeft: // 向左
			self.scopeSize = CGSizeMake(range, 0);
			self.oneWayscopeType = LCOneWayScopeTypeLeft;
		break;
		
		case LCOneWayScopeTypeBottom: // 向下
			self.scopeSize = CGSizeMake(0, range);
			self.oneWayscopeType = LCOneWayScopeTypeBottom;
		break;
		
		case LCOneWayScopeTypeRight: // 向右
			self.scopeSize = CGSizeMake(range, 0);
			self.oneWayscopeType = LCOneWayScopeTypeRight;
		break;
		
		default:
		break;
	}
}

/**
 * 设置 xy轴的点击范围 rangeX:X轴扩大或缩小距离 rangeY:Y轴扩大或缩小距离
 */
-(void)lc_setTwoWayClickScopeWithType:(LCTwoWayScopeType)scopetype rangeX:(CGFloat)rangeX rangeY:(CGFloat)rangeY{

	self.scopeSize = CGSizeMake(rangeX, rangeY);
	
	switch (scopetype) {
		case LCTwoWayScopeTypeAllAround: // 四周
			self.twoWayscopeType = LCTwoWayScopeTypeAllAround;
		break;
		
		case LCTwoWayScopeTypeUPLEFT: // 左上
			self.twoWayscopeType = LCTwoWayScopeTypeUPLEFT;
		break;
	
		case LCTwoWayScopeTypeLOWERLEFT: // 左下
			self.twoWayscopeType = LCTwoWayScopeTypeLOWERLEFT;
		break;
		
		case LCTwoWayScopeTypeUPRIGHT: // 右上
			self.twoWayscopeType = LCTwoWayScopeTypeUPRIGHT;
		break;
		
		case LCTwoWayScopeTypeLOWERRIGHT: // 右下
			self.twoWayscopeType = LCTwoWayScopeTypeLOWERRIGHT;
		break;
		
		default:
		break;
	}
}

-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event{

	// 获取当前视图的 bounds
	CGRect bounds = self.bounds;

	CGFloat scopeX = self.scopeSize.width;
	CGFloat scopeY = self.scopeSize.height;
	CGFloat boundsW = self.bounds.size.width;
	CGFloat boundsH = self.bounds.size.height;

	if (self.oneWayscopeType != 0) {
	
		switch (self.oneWayscopeType) {
			case LCOneWayScopeTypeHorizontal: // 水平
				bounds = CGRectInset(bounds, -scopeX, 0);
			break;
			case LCOneWayScopeTypeVertical: // 竖直
				bounds = CGRectInset(bounds, 0, -scopeY);
			break;
			case LCOneWayScopeTypeTop: // 向上
				bounds = CGRectMake(0, -scopeY/2, boundsW, boundsH);
				bounds = CGRectInset(bounds, 0, -scopeY/2);
			break;
			case LCOneWayScopeTypeLeft: // 向左
				bounds = CGRectMake(-scopeX/2, 0, boundsW, boundsH);
				bounds = CGRectInset(bounds, -scopeX/2, 0);
			break;
			case LCOneWayScopeTypeBottom: // 向下
				bounds = CGRectMake(0, scopeY/2, boundsW, boundsH);
				bounds = CGRectInset(bounds, 0, -scopeY/2);
			break;
			case LCOneWayScopeTypeRight: // 向右
				bounds = CGRectMake(scopeX/2, 0, boundsW, boundsH);
				bounds = CGRectInset(bounds, -scopeX/2, 0);
			break:
			default:
			break;
		}
	}

	if (self.twoWayscopeType != 0) {
		switch (self.twoWayscopeType) {
			case LCTwoWayScopeTypeAllAround: // 四周
				bounds = CGRectInset(bounds, -scopeX, -scopeY);
			break;
			case LCTwoWayScopeTypeUPLEFT: // 左上
				bounds = CGRectMake(-scopeX/2, -scopeY/2, boundsW, boundsH);
				bounds = CGRectInset(bounds, -scopeX/2, -scopeY/2);
			break;
			case LCTwoWayScopeTypeLOWERLEFT: // 左下
				bounds = CGRectMake(-scopeX/2, scopeY/2, boundsW, boundsH);
				bounds = CGRectInset(bounds, -scopeX/2, -scopeY/2);
			break;
			case LCTwoWayScopeTypeUPRIGHT: // 右上
				bounds = CGRectMake(scopeX/2, -scopeY/2, boundsW, boundsH);
				bounds = CGRectInset(bounds, -scopeX/2, -scopeY/2);
			break;
			case LCTwoWayScopeTypeLOWERRIGHT: // 右下
				bounds = CGRectMake(scopeX/2, scopeY/2, boundsW, boundsH);
				bounds = CGRectInset(bounds, -scopeX/2, -scopeY/2);
			break;

			default:
			break;
		}
	}
	return CGRectContainsPoint(bounds, point);
}