在UIView中绘制三角形切口以供选择指示

Fei*_*anZ 16 cocoa-touch core-animation core-graphics ios

我正在创建一个视图,作为我的应用程序的类别选择器.我希望它有一个剪切三角形作为选择指示,如下图所示:

自定义UI设计

我不知道如何绘制三角形,使其成为一个切口,露出下面的主视图.下面的主视图很可能有一个自定义的,可能是非重复的(我尚未决定)图像作为其背景.另外,我希望三角形在选择改变时动画到一个新位置,这进一步使事情变得复杂.

我意识到子视图会使动画更容易,但会使绘图复杂化; 直接绘制可能会使动画更难.而且我对Quartz不太熟悉,所以我不确定如何使用直接绘图路线.

提前致谢!

更新:我看过Matt Gallagher关于绘制带孔的形状的帖子,但它并没有真正回答我的问题.有没有办法让我"看到"我的形状中某条路径下面的东西,并复制它?...然后支持动画呢?

更新2:我通过简单地绘制一条额外的路径完成了部分工作.结果如下所示:http: //dl.dropbox.com/u/7828009/Category%20Selector.mov

代码:

CGRect cellRect = [self rectForCategoryNumber:(selectedCategoryIndex + 1)];
[[UIColor scrollViewTexturedBackgroundColor] setFill];
CGContextMoveToPoint(currentContext, self.frame.size.width, (cellRect.origin.y + cellRect.size.height * 0.15));
CGContextAddLineToPoint(currentContext, self.frame.size.width, (cellRect.origin.y + cellRect.size.height * 0.65));
CGContextAddLineToPoint(currentContext, self.frame.size.width * 0.8, (cellRect.origin.y + cellRect.size.height * 0.4));
CGContextClosePath(currentContext);
CGContextFillPath(currentContext);
[[UIColor darkGrayColor] setStroke];
CGContextSetLineCap(currentContext, kCGLineCapRound);
CGContextMoveToPoint(currentContext, self.frame.size.width, (cellRect.origin.y + cellRect.size.height * 0.15));
CGContextAddLineToPoint(currentContext, self.frame.size.width * 0.8, (cellRect.origin.y + cellRect.size.height * 0.4));
CGContextSetLineWidth(currentContext, 2.5);
CGContextStrokePath(currentContext);
[[UIColor lightGrayColor] setStroke];
CGContextMoveToPoint(currentContext,self.frame.size.width * 0.8, (cellRect.origin.y + cellRect.size.height * 0.4));
CGContextAddLineToPoint(currentContext, self.frame.size.width, (cellRect.origin.y + cellRect.size.height * 0.65));
CGContextSetLineWidth(currentContext, 1.0);
CGContextStrokePath(currentContext);
Run Code Online (Sandbox Code Playgroud)

显然,在这种情况下它只能起作用,因为我在两种情况下使用相同的填充颜色; 如果可能的话,我想消除这种依赖性.当然,我当然想要动画那个三角形的位置.

更新3:我尝试做的动画:

static CALayer *previousLayer = nil;
static CGMutablePathRef previousPath = nil;
// … Get context, etc.
CAShapeLayer *shapeLayer = [[CAShapeLayer alloc] init];
shapeLayer.path = shapePath;
[shapeLayer setFillColor:[[UIColor redColor] CGColor]];
[shapeLayer setStrokeColor:[[UIColor blackColor] CGColor]];
[shapeLayer setBounds:self.bounds];
[shapeLayer setAnchorPoint:self.bounds.origin];
[shapeLayer setPosition:self.bounds.origin];
if (previousPath) {     // Animate change
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"changePath"];
    animation.duration = 0.5;
    animation.fromValue = (id)previousPath;
    animation.toValue = (id)shapePath;
    [shapeLayer addAnimation:animation forKey:@"animatePath"];
    previousPath = shapePath;
}

if (previousLayer)
    [previousLayer removeFromSuperlayer];
previousLayer = shapeLayer;
[self.layer addSublayer:shapeLayer];
Run Code Online (Sandbox Code Playgroud)

Mat*_*ong 44

你看过CAShapeLayer了吗?您可以为选择窗格创建一个定义整个轮廓的路径,包括为需要屏蔽的每个状态排除三角形.然后,如果要通过设置lineWidth和strokeColor属性来显示图像中显示的轮廓,则可以描绘图层.那应该能够满足你的需求.CAShapeLayer中的path属性是可动画的,这意味着你要做的就是设置path属性并设置动画(假设你的图层是视图的子图层而不是根图层).

最好的祝福.

使用代码更新

这段代码:

- (void)viewDidLoad
{
  [super viewDidLoad];

  [[self view] setBackgroundColor:[UIColor blueColor]];

  CGMutablePathRef path = CGPathCreateMutable();
  CGPathMoveToPoint(path,NULL,0.0,0.0);
  CGPathAddLineToPoint(path, NULL, 160.0f, 0.0f);  
  CGPathAddLineToPoint(path, NULL, 160.0f, 100.0f);
  CGPathAddLineToPoint(path, NULL, 110.0f, 150.0f);
  CGPathAddLineToPoint(path, NULL, 160.0f, 200.0f);
  CGPathAddLineToPoint(path, NULL, 160.0f, 480.0f);
  CGPathAddLineToPoint(path, NULL, 0.0f, 480.0f);
  CGPathAddLineToPoint(path, NULL, 0.0f, 0.0f);


  CAShapeLayer *shapeLayer = [CAShapeLayer layer];
  [shapeLayer setPath:path];
  [shapeLayer setFillColor:[[UIColor redColor] CGColor]];
  [shapeLayer setStrokeColor:[[UIColor blackColor] CGColor]];
  [shapeLayer setBounds:CGRectMake(0.0f, 0.0f, 160.0f, 480)];
  [shapeLayer setAnchorPoint:CGPointMake(0.0f, 0.0f)];
  [shapeLayer setPosition:CGPointMake(0.0f, 0.0f)];
  [[[self view] layer] addSublayer:shapeLayer];

  CGPathRelease(path);

}
Run Code Online (Sandbox Code Playgroud)

结果显示:

在此输入图像描述

您可以在此处下载示例项目:

http://cl.ly/3J1B1f1l2423142l3X35