【iOS开发】根据图片透明度自定义UIButton实现

    日常开发过程中,经常会碰到自定义按钮的需求,例如:微信中的图片部分的尖角。本身就是根据聊天的气泡进行“塑形”的,如下图就是微信中图片“气泡化”显示。



要达成目标,我们需要解决的问题有下面几个:
1、点击没有图片的部分,不响应点击操作
2、根据指定的mask图片,进行图片合成&剪切

问题1:根据图片,设定响应区域

我们建立一个UIButton的子类,变量imageMask用来记录图片的形状,UIButton每次点击的时候,都会调用:
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event;
来判断当前点击的按钮是否需要响应,所以,我们在UIButton的子类(KMAutoShapeButton)中响应该函数:

// 判断当前point对应的alpha是否在0.1以内,设置的阀值是0.1
- (BOOL)isAlphaVisibleAtPoint:(CGPoint)point forImage:(UIImage *)image
{
    CGSize iSize = image.size;
    CGSize bSize = self.bounds.size;
    point.x *= (bSize.width != 0) ? (iSize.width / bSize.width) : 1;
    point.y *= (bSize.height != 0) ? (iSize.height / bSize.height) : 1;
    
    CGColorRef pixelColor = [[self.imageMask colorAtPixel:point] CGColor];
    CGFloat alpha = CGColorGetAlpha(pixelColor);
    return alpha >= kAlphaVisibleThreshold;
}

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
    // Return NO if even super returns NO (i.e., if point lies outside our bounds)
    BOOL superResult = [super pointInside:point withEvent:event];
    if (!superResult) {
        return superResult;
    }
    
    if (CGPointEqualToPoint(self.previousTouchPoint, point)) {
        return self.previousTouchHitTestResponse;
    }
    
    self.previousTouchPoint = point;
    self.previousTouchHitTestResponse = [self isAlphaVisibleAtPoint:point forImage:self.imageMask];
    return self.previousTouchHitTestResponse;
}

在-(BOOL)pointInside:withEvent: 中,先判断父类的结果并返回。
再次判断 当前点击位置是否等于上次的点击位置,如果是,返回上次的结果。在响应过程中一次点击可能会多次调用-(BOOL)pointInside:withEvent:
否则返回当前次判断返回结果。

问题2:根据制定的mask图片,进行图片合成&剪切
解决了问题1,我们只是能根据提供的mask图片检测响应区域,下面讨论怎么在:
- (void)setImage:(UIImage *)image forState:(UIControlState)state;
- (void)setBackgroundImage:(UIImage *)image forState:(UIControlState)state;
的函数里面对要设置的图片进行剪切。
在图片绘制CGContext系列函数里面, CGContextClipToMask 是根据指定mask图片的alpha值进行剪切,由此,我们可以通过mask图片&CGContextClipToMask 函数,将设置的Image进行剪切然后设置到UIButton中。

UIImage+shape.m剪切部分:

- (UIImage *)imageWithMask:(UIImage*)imageMask
{
    // 转换坐标
    imageMask = [imageMask flipVertical];
    
    UIGraphicsBeginImageContext(CGSizeMake(self.size.width, self.size.height));
    
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    CGImageRef maskRef = [imageMask fitSize:self.size].CGImage;
    
    CGContextClipToMask(context, CGRectMake(0, 0, self.size.width, self.size.height), maskRef);

    [self drawInRect:CGRectMake(0, 0, self.size.width, self.size.height)];
    UIImage *reSizeImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    
    
    return reSizeImage;
}

- (UIImage*)flipVertical
{
    UIImage *image = nil;
    switch (self.imageOrientation) {
        case UIImageOrientationUp:
        {
            image = [UIImage imageWithCGImage:self.CGImage scale:1 orientation:UIImageOrientationDownMirrored];
            break;
        }
        case UIImageOrientationDown:
        {
            image = [UIImage imageWithCGImage:self.CGImage scale:1 orientation:UIImageOrientationUpMirrored];
            break;
        }
        case UIImageOrientationLeft:
        {
            image = [UIImage imageWithCGImage:self.CGImage scale:1 orientation:UIImageOrientationLeftMirrored];
            break;
        }
        case UIImageOrientationRight:
        {
            image = [UIImage imageWithCGImage:self.CGImage scale:1 orientation:UIImageOrientationRightMirrored];
            break;
        }
        case UIImageOrientationUpMirrored:
        {
            image = [UIImage imageWithCGImage:self.CGImage scale:1 orientation:UIImageOrientationDown];
            break;
        }
        case UIImageOrientationDownMirrored:
        {
            image = [UIImage imageWithCGImage:self.CGImage scale:1 orientation:UIImageOrientationUp];
            break;
        }
        case UIImageOrientationLeftMirrored:
        {
            image = [UIImage imageWithCGImage:self.CGImage scale:1 orientation:UIImageOrientationLeft];
            break;
        }
        case UIImageOrientationRightMirrored:
        {
            image = [UIImage imageWithCGImage:self.CGImage scale:1 orientation:UIImageOrientationRight];
            break;
        }
        default:
            break;
    }
    
    return image;
}

KMAutoShapeButton.m重载图片设置部分:

// Reset the Hit Test Cache when a new image is assigned to the button
- (void)setImage:(UIImage *)image forState:(UIControlState)state
{
    [super setImage:self.imageMask ? [image imageWithMask:self.imageMask] : image forState:state];
    
    
    
    [self resetHitTestCache];
}

- (void)setBackgroundImage:(UIImage *)image forState:(UIControlState)state
{
    [super setBackgroundImage:self.imageMask ? [image imageWithMask:self.imageMask] : image forState:state];
    [self resetHitTestCache];
}



- (void)resetHitTestCache
{
    self.previousTouchPoint = CGPointMake(CGFLOAT_MIN, CGFLOAT_MIN);
    self.previousTouchHitTestResponse = NO;
}
通过 按钮点击检测、图片剪切 等步骤,可以得到我们最终需要的图片效果,并且在需要变换形状的时候,仅仅将mask图片替换掉即可。

代码下载:http://download.csdn.net/detail/u013494674/8046173

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值