不规则形状按钮的简易使用方法

6

我终于发布了我的主要应用程序(Tap Play MMO-快来看看吧;-)),现在我正在努力扩展它。

为此,我需要一个圆形,其中有四个单独的按钮,这些按钮本质上将成为四分之一。 我得出结论,圆形图像将需要由四个图像构成,每个图像都对应一个四分之一,但由于矩形图像形状的必要性,我最终会有一些重叠,尽管重叠部分将是透明的。

如何让它最好地工作? 我真的需要非常简单的东西,我已经查看了这个http://iphonedevelopment.blogspot.com/2010/03/irregularly-shaped-uibuttons.html,但还没有成功让它工作。 有人能提供一些建议吗?

如果有任何区别,我将部署到iOS 3.X框架(当iPad的4.2版本推出时,将会是4.2)。

3个回答

7
跳过按钮,直接响应包含圆形的视图中的触摸。为要捕获触摸的每个区域创建一个CGPath,当您的UIview接收到触摸时,请检查成员身份是否在路径内。以下是我解决问题的方法:(我尚未测试此代码,语法可能不完全正确,但这是大致的想法)1)使用PS或您喜欢的图像创建应用程序,创建一个四分之一圆的png。将其添加到XCode项目中。2)向UI添加UIView。将UIView的层内容设置为png。
self.myView = [[UIView alloc] initWithRect:CGRectMake(10.0, 10.0, 100.0, 100,0)];
[myView.layer setContents:(id)[UIImage loadImageNamed:@"my.png"]];

3) 创建CGPaths,描述您感兴趣的UIView区域。

self.quadrantOnePath = CGPathCreateMutable();
CGPathMoveToPoint(self.quadrantOnePath, NULL, 50.0, 50.0);
CGPathAddLineToPoint(self.quadrantOnePath, NULL, 100.0, 50.0);
CGPathAddArc(self.quadrantOnePath, NULL, 50.0, 50.0, 50.0, 0.0, M_PI2, 1);
CGPathCloseSubpath(self.quadrantOnePath);

// create paths for the other 3 circle quadrants too!

4) 添加一个UIGestureRecognizer并监听/观察视图中的轻击手势

UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleGesture:)];
[tapRecognizer setNumberOfTapsRequired:2]; // default is 1

5) 当tapRecognizer调用其目标选择器时

- (void)handleGesture:(UIGestureRecognizer *) recognizer {

  CGPoint touchPoint = [recognizer locationOfTouch:0 inView:self.myView];
  bool processTouch = CGPathContainsPoint(self.quadrantOnePath, NULL, touchPoint, true);

  if(processTouch) {
     // call your method to process the touch
  }
}

在适当的时候不要忘记释放所有东西 -- 使用CGPathRelease来释放路径。

另一个想法:如果你用来表示圆形象限的图形仅仅是一个填充颜色(即没有花哨的图形,层效果等),你也可以使用UIView的drawRect方法中创建的路径来绘制象限。这将解决上述方法的一个缺陷:图形和用于检测触摸的路径之间没有紧密的集成。也就是说,如果你更换图形,改变图形的大小等,用于检测触摸的路径将失去同步。潜在地需要高维护性的代码。


这将是最理想和最简洁的解决方案 - 你能详细说明如何做到这一点吗? - David26th
编辑了上面的答案,以说明一种实现该功能的方法。 - TomH

5
我不明白为什么需要重叠。
只需创建4个按钮,并为每个按钮分配你的图像的一部分即可。

评论后编辑

看看这个伟大的项目,其中一个示例正是你想要做的。

它通过将被覆盖的像素的alpha值纳入pointInside:withEvent:和UIImage的类别中添加此方法来实现。

- (UIColor *)colorAtPixel:(CGPoint)point {
    // Cancel if point is outside image coordinates
    if (!CGRectContainsPoint(CGRectMake(0.0f, 0.0f, self.size.width, self.size.height), point)) {
        return nil;
    }


    // Create a 1x1 pixel byte array and bitmap context to draw the pixel into.
    // Reference: https://dev59.com/w3NA5IYBdhLWcg3wPLL-
    NSInteger pointX = trunc(point.x);
    NSInteger pointY = trunc(point.y);
    CGImageRef cgImage = self.CGImage;
    NSUInteger width = self.size.width;
    NSUInteger height = self.size.height;
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    int bytesPerPixel = 4;
    int bytesPerRow = bytesPerPixel * 1;
    NSUInteger bitsPerComponent = 8;
    unsigned char pixelData[4] = { 0, 0, 0, 0 };
    CGContextRef context = CGBitmapContextCreate(pixelData, 
                                                 1,
                                                 1,
                                                 bitsPerComponent, 
                                                 bytesPerRow, 
                                                 colorSpace,
                                                 kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
    CGColorSpaceRelease(colorSpace);
    CGContextSetBlendMode(context, kCGBlendModeCopy);

    // Draw the pixel we are interested in onto the bitmap context
    CGContextTranslateCTM(context, -pointX, pointY-(CGFloat)height);
    CGContextDrawImage(context, CGRectMake(0.0f, 0.0f, (CGFloat)width, (CGFloat)height), cgImage);
    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];
}

如果那是那么简单就好了。我的需求是把它旋转45度,所以很不幸,情况并不是那么简单。 - David26th
我必须承认,我错过了你的编辑 - 我不得不改变我的方法,尝试在一张图片上叠加触摸事件(虽然有些混乱),因为我的图像没有完全吻合。话虽如此,我将稍后测试答案,并标记它为正确的,以便问题有一个答案。 - David26th
我忘了提到,使用这种解决方案,您可以保留 OBShapedButton 从 UIButton 继承的完整功能,特别是在 InterfaceBuilder 中。 - vikingosegundo

4

1
参考技术的另一个链接:http://oleb.net/blog/2009/10/obshapedbutton-non-rectangular-buttons-on-the-iphone/ - Bijoy Thangaraj
这个链接项目的功能非常丰富,而且付出的努力很少。真的值得一看! - Gavin Miller

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接