UIButton 在使用有透明的 png 圖檔時
即使點到透明的部份依然會觸發 touch 事件
為了達到更準確的點擊效果
需要繼承 UIButton 類別
修改 -(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event 的觸發條件
並擴展 UIImage 類別的功能
以便根據 UIButton 所造成的圖片縮放取得點擊位置 pixel 資料
建立 UIImage+GetPixelRGBA
UIImage+GetPixelRGBA.h
@interface UIImage (GetPixelRGBA)
-(UIColor *)colorAtPoint:(CGPoint)point WithImageSize:(CGSize)size;
-(UIImage *)reSizeImage:(UIImage *)image toSize:(CGSize)reSize;
@end
UIImage+GetPixelRGBA.m
@implementation UIImage (GetPixelRGBA)
//取得 pixel UIColor
-(UIColor*)colorAtPoint:(CGPoint)point WithImageSize:(CGSize)size{
UIImage *resizeimage = [self reSizeImage:self toSize:size];
CGRect rect = CGRectMake(0.0f, 0.0f, resizeimage.size.width, resizeimage.size.height);
if (CGRectContainsPoint(rect, point) == NO) {return nil;}
CGImageRef image = resizeimage.CGImage;
size_t width = CGImageGetWidth(image);
size_t height = CGImageGetHeight(image);
int bytesPerPixel = 4;
int bytesPerRow = (bytesPerPixel*1); // 8bpp
unsigned char pixelData[4] = {0, 0, 0, 0};
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(pixelData, 1, 1, 8, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast|kCGBitmapByteOrder32Big);
CGColorSpaceRelease(colorSpace);
if (context == NULL) {
NSLog(@"[colorAtPixel] Unable to create context!");
return nil;
}
CGContextSetBlendMode(context, kCGBlendModeCopy);
CGFloat pointX = point.x;
CGFloat pointY = height-point.y;
CGContextTranslateCTM(context, -pointX, -pointY);
CGContextDrawImage(context, CGRectMake(0.0f, 0.0f, (CGFloat)width, (CGFloat)height), image);
CGContextRelease(context);
//Convert color values [0..255] to floats [0.0..1.0]
CGFloat red = (CGFloat)pixelData[0]/255.0f;
CGFloat green = (CGFloat)pixelData[1]/255.0f;
CGFloat blue = (CGFloat)pixelData[2]/255.0f;
CGFloat alpha = (CGFloat)pixelData[3]/255.0f;
return [UIColor colorWithRed:red green:green blue:blue alpha:alpha];
}
//改變 UIIamge 圖片大小
-(UIImage *)reSizeImage:(UIImage *)image toSize:(CGSize)reSize
{
UIGraphicsBeginImageContext(CGSizeMake(reSize.width, reSize.height));
[image drawInRect:CGRectMake(0, 0, reSize.width, reSize.height)];
UIImage *reSizeImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return reSizeImage;
}
@end
建立 NonRectButton
直接覆寫 UIButton 原有方法
另外記得要 import 剛剛擴展的 UIImage 方法
NonRectButton.m
#import "NonRectButton.h"
#import "UIImage+GetPixelRGBA.h"
@implementation NonRectButton
-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
// We can't test the image's alpha channel if the button has no image. Fall back to super.
UIImage *image = [self backgroundImageForState:UIControlStateNormal];
if (image == nil) {return YES;}
//NSLog(@"b %@", NSStringFromCGPoint(point));
CGColorRef color = [[image colorAtPoint:point WithImageSize:self.frame.size] CGColor];
CGFloat alphaValue = CGColorGetAlpha(color);
return (alphaValue >= 0.1f);
}
@end
最後在 ViewController 上實作 NonRectButton
記得要 import NonRectButton.h
MainViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
[self.view setBackgroundColor:[UIColor whiteColor]];
NonRectButton *button = [NonRectButton buttonWithType:UIButtonTypeCustom];
[button setFrame:CGRectMake(60, 60, 200, 200)];
[button setBackgroundImage:[UIImage imageNamed:@"star.png"] forState:UIControlStateNormal];
[self.view addSubview:button];