3 回答

TA貢獻1946條經驗 獲得超4個贊
對于任何其他想知道如何根據(jù)Costique建議使用Core Graphics繪制內部陰影的人,這就是如何:(在iOS上根據(jù)需要進行調整)
在您的drawRect:方法中...
CGRect bounds = [self bounds];
CGContextRef context = UIGraphicsGetCurrentContext();
CGFloat radius = 0.5f * CGRectGetHeight(bounds);
// Create the "visible" path, which will be the shape that gets the inner shadow
// In this case it's just a rounded rect, but could be as complex as your want
CGMutablePathRef visiblePath = CGPathCreateMutable();
CGRect innerRect = CGRectInset(bounds, radius, radius);
CGPathMoveToPoint(visiblePath, NULL, innerRect.origin.x, bounds.origin.y);
CGPathAddLineToPoint(visiblePath, NULL, innerRect.origin.x + innerRect.size.width, bounds.origin.y);
CGPathAddArcToPoint(visiblePath, NULL, bounds.origin.x + bounds.size.width, bounds.origin.y, bounds.origin.x + bounds.size.width, innerRect.origin.y, radius);
CGPathAddLineToPoint(visiblePath, NULL, bounds.origin.x + bounds.size.width, innerRect.origin.y + innerRect.size.height);
CGPathAddArcToPoint(visiblePath, NULL, bounds.origin.x + bounds.size.width, bounds.origin.y + bounds.size.height, innerRect.origin.x + innerRect.size.width, bounds.origin.y + bounds.size.height, radius);
CGPathAddLineToPoint(visiblePath, NULL, innerRect.origin.x, bounds.origin.y + bounds.size.height);
CGPathAddArcToPoint(visiblePath, NULL, bounds.origin.x, bounds.origin.y + bounds.size.height, bounds.origin.x, innerRect.origin.y + innerRect.size.height, radius);
CGPathAddLineToPoint(visiblePath, NULL, bounds.origin.x, innerRect.origin.y);
CGPathAddArcToPoint(visiblePath, NULL, bounds.origin.x, bounds.origin.y, innerRect.origin.x, bounds.origin.y, radius);
CGPathCloseSubpath(visiblePath);
// Fill this path
UIColor *aColor = [UIColor redColor];
[aColor setFill];
CGContextAddPath(context, visiblePath);
CGContextFillPath(context);
// Now create a larger rectangle, which we're going to subtract the visible path from
// and apply a shadow
CGMutablePathRef path = CGPathCreateMutable();
//(when drawing the shadow for a path whichs bounding box is not known pass "CGPathGetPathBoundingBox(visiblePath)" instead of "bounds" in the following line:)
//-42 cuould just be any offset > 0
CGPathAddRect(path, NULL, CGRectInset(bounds, -42, -42));
// Add the visible path (so that it gets subtracted for the shadow)
CGPathAddPath(path, NULL, visiblePath);
CGPathCloseSubpath(path);
// Add the visible paths as the clipping path to the context
CGContextAddPath(context, visiblePath);
CGContextClip(context);
// Now setup the shadow properties on the context
aColor = [UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:0.5f];
CGContextSaveGState(context);
CGContextSetShadowWithColor(context, CGSizeMake(0.0f, 1.0f), 3.0f, [aColor CGColor]);
// Now fill the rectangle, so the shadow gets drawn
[aColor setFill];
CGContextSaveGState(context);
CGContextAddPath(context, path);
CGContextEOFillPath(context);
// Release the paths
CGPathRelease(path);
CGPathRelease(visiblePath);
因此,基本上有以下步驟:
創(chuàng)建你的道路
設置所需的填充顏色,將此路徑添加到上下文中,然后填充上下文
現(xiàn)在創(chuàng)建一個更大的矩形,可以綁定可見路徑。在關閉此路徑之前,請?zhí)砑涌梢娐窂?。然后關閉路徑,以便創(chuàng)建一個形狀,其中減去了可見路徑。您可能要研究填充方法(偶數(shù)/奇數(shù)的非零纏繞),具體取決于創(chuàng)建這些路徑的方式。本質上,要使子路徑在將它們添加在一起時“減去”,您需要沿相反的方向(一個順時針方向,另一個逆時針方向)繪制(或構造)它們。
然后,您需要將可見路徑設置為上下文上的剪切路徑,以免在屏幕外繪制任何內容。
然后在上下文上設置陰影,包括陰影,模糊和顏色。
然后在大形狀中填充孔。顏色無關緊要,因為如果您正確完成所有操作,就不會看到此顏色,而只會看到陰影。

TA貢獻1995條經驗 獲得超2個贊
我知道我參加這個聚會遲到了,但這本可以幫助我在旅途中盡早找到...
為了在信用到期的地方提供信用,這本質上是對丹尼爾·索普(Daniel Thorpe)關于科斯蒂克(Costique)從較大區(qū)域中減去較小區(qū)域的解決方案的闡述的改進。此版本適用于使用圖層合成而不是覆蓋的用戶-drawRect:
該CAShapeLayer級可以用來達到同樣的效果:
CAShapeLayer* shadowLayer = [CAShapeLayer layer];
[shadowLayer setFrame:[self bounds]];
// Standard shadow stuff
[shadowLayer setShadowColor:[[UIColor colorWithWhite:0 alpha:1] CGColor]];
[shadowLayer setShadowOffset:CGSizeMake(0.0f, 0.0f)];
[shadowLayer setShadowOpacity:1.0f];
[shadowLayer setShadowRadius:5];
// Causes the inner region in this example to NOT be filled.
[shadowLayer setFillRule:kCAFillRuleEvenOdd];
// Create the larger rectangle path.
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddRect(path, NULL, CGRectInset(bounds, -42, -42));
// Add the inner path so it's subtracted from the outer path.
// someInnerPath could be a simple bounds rect, or maybe
// a rounded one for some extra fanciness.
CGPathAddPath(path, NULL, someInnerPath);
CGPathCloseSubpath(path);
[shadowLayer setPath:path];
CGPathRelease(path);
[[self layer] addSublayer:shadowLayer];
在這一點上,如果您的父層沒有對它的邊界進行遮罩,您將在該遮罩的邊緣周圍看到遮罩層的額外區(qū)域。如果您直接復制示例,這將是42像素的黑色。要擺脫它,您可以簡單地使用CAShapeLayer具有相同路徑的另一個并將其設置為陰影層的蒙版:
CAShapeLayer* maskLayer = [CAShapeLayer layer];
[maskLayer setPath:someInnerPath];
[shadowLayer setMask:maskLayer];
我自己尚未對此進行基準測試,但是我懷疑將這種方法與柵格化結合使用比覆蓋更有效-drawRect:。
- 3 回答
- 0 關注
- 1322 瀏覽
添加回答
舉報