【问题标题】:Applying a stroke to a rounded rect in core-graphics将笔划应用于核心图形中的圆角矩形
【发布时间】:2010-02-02 04:14:18
【问题描述】:

我有一个带有圆角的渐变,用于自定义 UITableViewCell 背景。我正在尝试对路径应用描边,但不能完全做到,而且看不到哪里出错了。

  CGFloat minx = CGRectGetMinX(rect) , midx = CGRectGetMidX(rect), maxx = CGRectGetMaxX(rect) ;
  CGFloat miny = CGRectGetMinY(rect) , maxy = CGRectGetMaxY(rect) ;
  minx = minx + 1;
  miny = miny ;

  maxx = maxx - 1;
  maxy = maxy - 1;

  CGContextMoveToPoint(c, minx, miny);
  CGContextAddArcToPoint(c, minx, maxy, midx, maxy, kDefaultMargin);
  CGContextAddArcToPoint(c, maxx, maxy, maxx, miny, kDefaultMargin);
  CGContextAddLineToPoint(c, maxx, miny);
  CGContextAddLineToPoint(c, minx, miny);

  // Fill and stroke the path
  CGContextClip(c);
  CGContextStrokePath(c);  

  CGFloat locations[2] = { 0.0, 1.0 };
  CGFloat mycomponents[8] = TABLE_CELL_BACKGROUND;
  CGColorSpaceRef myColorspace = CGColorSpaceCreateDeviceRGB();
  CGGradientRef myGradient = CGGradientCreateWithColorComponents(myColorspace, mycomponents, locations, 2);
  CGContextDrawLinearGradient(c, myGradient, CGPointMake(minx,miny), CGPointMake(minx,maxy), 0);
  CGGradientRelease(myGradient);
  CGColorSpaceRelease(myColorspace);

此代码将矩形右圆化并应用渐变,但不描边行。我的错在哪里?

alt text http://grab.by/26Ye



编辑: 根据 subw 的建议,我将代码更改为:

    CGContextRef c = UIGraphicsGetCurrentContext();
    CGColorSpaceRef myColorspace = CGColorSpaceCreateDeviceRGB();
    CGGradientRef myGradient = nil;
    CGFloat components[8] = TABLE_CELL_BACKGROUND;
    CGContextSetFillColorWithColor(c, [[UIColor redColor] CGColor]);
    CGContextSetStrokeColorWithColor(c, [[UAColor redColor] CGColor]);
    CGContextSetLineWidth(c, 2);

    CGFloat minx = CGRectGetMinX(rect) , midx = CGRectGetMidX(rect), maxx = CGRectGetMaxX(rect) ;
    CGFloat miny = CGRectGetMinY(rect) , maxy = CGRectGetMaxY(rect) ;
    minx = minx + 1;
    miny = miny ;

    maxx = maxx - 1;
    maxy = maxy - 1;

    CGContextMoveToPoint(c, minx, miny);
    CGContextAddArcToPoint(c, minx, maxy, midx, maxy, kDefaultMargin);
    CGContextAddArcToPoint(c, maxx, maxy, maxx, miny, kDefaultMargin);
    CGContextAddLineToPoint(c, maxx, miny);
    CGContextAddLineToPoint(c, minx, miny);

    // Fill and stroke the path
    CGContextSaveGState(c);
    CGContextClip(c);

    CGFloat locations[2] = { 0.0, 1.0 };
    CGFloat mycomponents[8] = TABLE_CELL_BACKGROUND;
    CGColorSpaceRef myColorspace = CGColorSpaceCreateDeviceRGB();
    myGradient = CGGradientCreateWithColorComponents(myColorspace, mycomponents, locations, 2);
    CGContextDrawLinearGradient(c, myGradient, CGPointMake(minx,miny), CGPointMake(minx,maxy), 0);

    CGContextRestoreGState(c);
    CGContextStrokePath(c);

但是矩形是这样出来的……

alt text http://grab.by/2714

...没有边框。如果我将CGContextStrokePath(c) 更改为CGContextStrokeRect(c, rect),则会出现笔划(我将其设为红色以进行说明)。但不知何故,在抚摸路径时,我没有得到任何抚摸:(

alt text http://grab.by/27aM

【问题讨论】:

    标签: iphone uitableview core-graphics drawrect stroke


    【解决方案1】:

    响应您修改后的代码,我引用文档:

    与当前路径不同,当前剪切路径是图形状态的一部分。因此,要通过将剪切路径恢复到之前的状态来重新扩大可绘制区域,您必须在剪切之前保存图形状态,并在完成任何剪切后恢复图形状态。

    确定新的剪辑路径后,该函数将上下文的当前路径重置为空路径。

    CGContextClip

    因此,当前的绘制路径不是图形状态的一部分。所以这就是你正在做的事情:

    1. 构建绘图路径
    2. 保存 gstate
    3. 将当前绘图路径添加到剪切路径; 清除当前绘制路径
    4. 绘制渐变
    5. 恢复 gstate(之前的剪切路径已恢复;绘图路径保持为空)
    6. 无中风

    解决方案是将路径绘制到 CGPath 对象中,然后在剪切之前(保存 gstate 之后)和描边之前将其添加为当前路径。

    您还应该决定是否希望这是外部笔划、内部笔划或居中笔划。对于居中的笔划,在未剪裁的情况下进行笔划。对于内部笔划,在剪裁时进行笔划。对于外部描边,反转路径,然后剪辑,然后描边。您需要将最后两种形式的线宽加倍,因为您将剪掉一半的笔划。

    如果我将CGContextStrokePath(c) 更改为CGContextStrokeRect(c, rect),就会出现笔划。

    因为该函数在描边之前将该矩形的路径添加到当前绘图路径。

    【讨论】:

    • 为什么设置剪切路径时会清除当前路径? CGContextClip 的文档没有提到这一点。
    • subw:是的。 “确定新的剪切路径后,该函数将上下文的当前路径重置为空路径。”它这样做是因为 PostScript(PDF 的直接祖先)就是这样做的。
    • 有道理。我今晚试试这个
    • 效果很好。也许我的逻辑不是最好的,但这是一个新的 SO 问题要问:)
    • 尊敬的 Core Graphics GURU,如果您想帮助解决其他问题,请点击此处:stackoverflow.com/questions/2181279/…
    【解决方案2】:

    不确定,但也许您正在笔划上绘制渐变?

    【讨论】:

    • 我不这么认为。我正在更新代码中的渐变之后绘制笔画。
    【解决方案3】:

    您要么在笔划上绘制渐变,和/或剪裁您笔划的区域。

    我认为以下可能会更好:

    CGContextSaveGState(c);
    CGContextClip(c);
    
    //gradient drawing stuff
    
    CGContextRestoreGState(c);
    CGContextStrokePath(c);
    

    当然,你还必须正确设置笔触颜色和宽度。

    【讨论】:

    • 还有一个问题:您是否在某处调用了 CGContextBeginPath(c)?如果没有,那可能是个问题。
    • 我没有。我已经更新了代码以显示我在绘制单元格的这部分代码之前所拥有的内容。
    • 去掉所有的剪裁、渐变绘制和保存恢复图形状态的东西,是不是画出了路径?如果是这样,Peter Hoseys 的回答可能是正确的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-02
    • 2018-08-14
    相关资源
    最近更新 更多