代码库> 按钮> IOS不规则UIButton依赖颜色值实现
IOS不规则UIButton依赖颜色值实现
关注
上传者:小哈加尔 分类:按钮(Button)
查看次数:13936 下载次数:541
上传时间:2012-10-31 大小:5 B
实现代码详见附件,直接导入工程即可使用菜鸟一枚,高手勿喷


PS:对于性能高敏感的地方不适合使用本方法。

第一次发帖,见谅

//
//  XMagicButton.h
//  
//
//  Created by 仙人掌 on 12-10-31.
//  Copyright (c) 2012年 仙人掌. All rights reserved.
//
//
//------------------------------------------------------------------------------------------------------
// XMagicButton是一个特殊的按钮类,这个按钮可以透过指定颜色
// 一共有三种透过颜色方式:1 指定颜色alpha值透过 2指定颜色RGB值透过 3指定alpha值和RGB值透过
// 根据需要设定XMagicButton的check_mask属性即可
// 依赖框架:
//        UIkit.framework
//        CoreGraphics.framework
//------------------------------------------------------------------------------------------------------
// 定义FLOAT_MIN用来判断浮点数是否相等时的误差,因为不需要很高计算精度,所以定义为10e-5
#define FLOAT_MIN 0.0001

#define TO_RGB(x) ((x)/(255.0))
// 定义FLOAT_EQUAL(num1,num2),用来比较两个浮点数是否相等
#define FLOAT_EQUAL(num1,num2) ({ (ABS(num1)) - (ABS(num2)) < (FLOAT_MIN) ? YES : NO; })

// 定义检查类型CHECK_MASK枚举,
// CM_ALPHA_ONLY 只检查颜色的alpha值是否相等,如果两个颜色的alpha值相等,则认为颜色是相同的
// CM_COLOR_ONLY 只检查颜色的RGB值是否相等,如果两个颜色的RGB值相等,则认为颜色是相同的
// CM_MASK_ALL   同时检查颜色的RGB值和alpha值是否相等,只有都相等的时候,认为颜色是相同的
typedef enum{
    CM_ALPHA_ONLY = 0,
    CM_COLOR_ONLY,
    CM_MASK_ALL,
}CHECK_MASK;

// 通过UIImage创建一个CGContextRef(CGBitmapContextRef)
// 使用色彩控件为DeviceRGB
// 每个色彩 8 bite
// kCGImageAlphaPremultipliedFirst
// 返回的 CGContextRef不会自动释放,需要调用CGContextRefRelease来释放
CGContextRef CreateABitmapContext(UIImage * img);

//判断point是否在矩形rect内,
//{0,0}在矩形范围内,{width,0}和{0,height}不在范围内
BOOL PointInRect(CGPoint point,CGRect rect);

// 通过传入的CGPoint 和 CGContextRef返回在该CGContextRef对应点的颜色
UIColor * GetColor(CGPoint point,CGContextRef cr);

// 通过传入point,Image,TargetColor和mask判断在图像Image中Point点所在的像素颜色值是否为TargetColor颜色
// 判断方式位mask
// 如果point不在Image的Frame中抛出异常
// 如果nil == Image抛出异常
// 如果nil == TargetColor,返回NO
// 如果mask不在范围内,抛出异常
// 如果通过Image产生的CGContext == NULL 则会抛出异常
BOOL PointColorInImageIsTargetColor(CGPoint point, UIImage * Image,UIColor *targetColor,CHECK_MASK mask);
//
#import

@interface XMagicButton : UIButton{
    CHECK_MASK check_mask_;
    UIColor * maskColor_;
    
}
@property ( retain ) UIColor * maskColor;
@property ( assign ) CHECK_MASK check_mask;
@end
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//
//  XMagicButton.m
//  
//
//  Created by 仙人掌 on 12-10-31.
//  Copyright (c) 2012年 仙人掌. All rights reserved.
//

static const NSInteger BYTE_PerPixel = 4;
static const NSInteger BITS_PerComponent = 8;

#import "XMagicButton.h"

CGContextRef CreateABitmapContext(UIImage * img){
//    使用RGB色彩空间
    CGColorSpaceRef csr = CGColorSpaceCreateDeviceRGB();
    void * bitmapData = NULL;
    CGContextRef cr = NULL;
    size_t width = img.size.width;
    size_t height = img.size.height;
//    申请bitmapData内存空间
    bitmapData = malloc(BYTE_PerPixel * width * height);
    cr = CGBitmapContextCreate(bitmapData, width, height, BITS_PerComponent, BYTE_PerPixel * width, csr, kCGImageAlphaPremultipliedFirst);
    CGColorSpaceRelease(csr);
    if ( NULL == cr ){
//        如果创建Context失败,则释放Malloc申请的内存,如果成功则不用单独释放,
//        Context会持有数据指针,在CGContextRelease会释放这块内存
        free(bitmapData);
        return NULL;
    }
//    将创建的上下文压入栈顶
    UIGraphicsPushContext(cr);
//    在栈顶上下文中绘图,即可理解为讲Bitmap数据填入bitmapData
    [img drawAtPoint:CGPointZero];
//    弹出栈顶上下文
    UIGraphicsPopContext();
    return cr;
}

BOOL PointInRect(CGPoint point,CGRect rect){
    if ( point.x < rect.origin.x || point.x >= rect.size.width ||
        point.y < rect.origin.x || point.y >= rect.size.height)
        return NO;
    else
        return YES;
}

UIColor * GetColor(CGPoint point,CGContextRef cr){
    size_t width = CGBitmapContextGetWidth(cr);
    unsigned char * bitmapData = NULL;
//    指向位图数据
    bitmapData = CGBitmapContextGetData(cr);
    if ( NULL == bitmapData ){
        @throw [NSException exceptionWithName:@"Failed To Create Context" reason:@"UnKnow" userInfo:nil];
    }
    int alpha = 0, red = 0, green = 0, blue = 0;
//    四舍五入
    int offset = BYTE_PerPixel * (round( point.y ) * width + round( point.x ));
    alpha = ( int )bitmapData[ offset ];    //第一个字节 由 kCGImageAlphaPremultipliedFirst 决定
    red   = ( int )bitmapData[ offset + 1 ];
    green = ( int )bitmapData[ offset + 2 ];
    blue  = ( int )bitmapData[ offset + 3 ];
    
    UIColor * resultColor = [UIColor colorWithRed:TO_RGB(red) green:TO_RGB(green) blue:TO_RGB(blue) alpha:TO_RGB(alpha)];
    return resultColor;
}

BOOL PointColorInImageIsTargetColor(CGPoint point, UIImage * Image,UIColor *targetColor,CHECK_MASK mask){
    CGContextRef bitmapRef = NULL;
    if ( nil == Image){
        @throw [NSException exceptionWithName:@"Parameter Invalid" reason:@" The Parameter Is nil" userInfo:nil];
    }
    CGRect frame = CGRectMake(0, 0, Image.size.width, Image.size.height);
    if ( NO == PointInRect(point, frame)){
        @throw [NSException exceptionWithName:@"Parameter Invalid" reason:@"The Point is Out of Rang" userInfo:nil];
    }
    if ( mask < CM_ALPHA_ONLY || mask > CM_MASK_ALL )
        @throw [NSException exceptionWithName:@"Parameter Invalid" reason:@"mask Invalid" userInfo:nil];
    if ( nil == targetColor )
        return NO;
//    
    bitmapRef = CreateABitmapContext(Image);
    if ( NULL == bitmapRef ){
        @throw [NSException exceptionWithName:@"bitmapRef is NULL" reason:@"UnKnow" userInfo:nil];
    }
    
    UIColor * colorInImage = GetColor(point, bitmapRef);
    if ( CM_ALPHA_ONLY == mask){
        float alpha_colorInImage = CGColorGetAlpha(colorInImage.CGColor);
        float alpha_colorTarget  = CGColorGetAlpha(targetColor.CGColor);
        return FLOAT_EQUAL(alpha_colorInImage,alpha_colorTarget);
    }
    else{
        BOOL result = NO;
        result = CGColorEqualToColor(colorInImage.CGColor, targetColor.CGColor);
        if ( CM_MASK_ALL == mask ){
            float alpha_colorInImage = CGColorGetAlpha(colorInImage.CGColor);
            float alpha_colorTarget  = CGColorGetAlpha(targetColor.CGColor);
            result = FLOAT_EQUAL(alpha_colorInImage,alpha_colorTarget);
        }
        return result;
    }
    CGContextRelease(bitmapRef);
}

@implementation XMagicButton
@synthesize check_mask = check_mask_;
@synthesize maskColor = maskColor_;
- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
        self = [self init];
    }
    return self;
}

-(id)init{
    self = [super init];
    if ( self ){
        self.check_mask = CM_ALPHA_ONLY;
        self.maskColor = [UIColor clearColor];
    }
    return self;
}

-(void)awakeFromNib{
    self.check_mask = CM_ALPHA_ONLY;
    self.maskColor = [UIColor clearColor];
}

-(void)dealloc{
    [self.maskColor release], self.maskColor = nil;
    [super dealloc];
}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    if ( self.imageView.image != nil ){
        UITouch * touch = [touches anyObject];
        UIImageView * imgView = self.imageView;
        CGPoint touchPoint = [touch locationInView:imgView];
        CGRect frame = CGRectMake(0, 0, imgView.image.size.width, imgView.image.size.height);
        if ( NO == PointInRect(touchPoint, frame) )
        {
            [[self nextResponder]touchesBegan:touches withEvent:event];
            return;
        }
        BOOL result = PointColorInImageIsTargetColor(touchPoint, imgView.image, self.maskColor, self.check_mask);
        if ( result == NO ){
            [super touchesBegan:touches withEvent:event];
        }
        else{
            [[self nextResponder] touchesBegan:touches withEvent:event];
        }
    }
    else{
        [super touchesBegan:touches withEvent:event];
    }
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
    // Drawing code
}
*/

@end




收藏
我来说两句
发表评论
您还没有登录!请登录注册
所有评论(0
提示
sina weixin mail 回到顶部