第七篇、hitTest UITabbar中间突出按钮额外增加可点击区域

简介:
  以前UITabbar使用中间有一个凸起按钮时,常常就需要用到hitTest来处理可点击的范围。

示例代码
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
     UIView *hitView = nil;
     //NSLog(@"point:%@", NSStringFromCGPoint(point));
     UIButton *roundBtn = (UIButton *)[self viewWithTag:10086];
     UIButton *leftBtn = (UIButton *)[self viewWithTag:10087];
     UIButton *rightBtn = (UIButton *)[self viewWithTag:10088];
     BOOL pointInRound = [self touchPointInsideCircle:roundBtn.center radius:30 targetPoint:point];
     if (pointInRound) {
         hitView = roundBtn;
     } else if(CGRectContainsPoint(leftBtn.frame, point)) {
         hitView  = leftBtn;
     } else if(CGRectContainsPoint(rightBtn.frame, point)) {
         hitView = rightBtn;
     } else {
         hitView = self;
     }
     return hitView;
 }

 

增加categ,可以拓展按钮的点击范围:

#import <UIKit/UIKit.h>

@interface UIButton (EnlargeTouchArea)

/**
 *  扩大 UIButton 的點擊範圍
 *  控制上下左右的延長範圍
 *
 *  @param top    <#top description#>
 *  @param right  <#right description#>
 *  @param bottom <#bottom description#>
 *  @param left   <#left description#>
 */
- (void)setEnlargeEdgeWithTop:(CGFloat)top right:(CGFloat)right bottom:(CGFloat)bottom left:(CGFloat)left;

@end

 

#import "UIButton+Category.h"
#import <objc/runtime.h>
@implementation UIButton (EnlargeTouchArea)

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

- (void)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)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;
    }
}

- (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

 

另一种实现方式:扩大按钮的点击区域

要扩大UIButton的点击事件响应范围,只需要重写UIButton的hitTest方法

//将点击事件响应范围扩大到周边20个点
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    CGRect rect = self.frame;

    //新的响应事件的区域
    //这里的区域是在父控件坐标系内的
    rect.origin.x -= 20;
    rect.origin.y -= 20;
    rect.size.height += 20 * 2;
    rect.size.width += 20 * 2;

    //将点转换到与响应事件的区域在同一个坐标系内
    CGPoint p = [self convertPoint:point toView:self.superview];

    //判断点是否在新的事件响应区域内
    if (CGRectContainsPoint(rect, p))
    {
        return self;
    }
    else
    {
        return [super hitTest:point withEvent:event];
    }
}

 

posted on 2016-08-21 19:44  久冬不雨  阅读(473)  评论(0编辑  收藏  举报