首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >UIView层上的内部阴影效果?

UIView层上的内部阴影效果?
EN

Stack Overflow用户
提问于 2010-12-14 00:55:38
回答 17查看 82.2K关注 0票数 92

我有以下CALayer:

CAGradientLayer *gradient = [CAGradientLayer layer];
gradient.frame = CGRectMake(8, 57, 296, 30);
gradient.cornerRadius = 3.0f;
gradient.colors = [NSArray arrayWithObjects:(id)[RGB(130, 0, 140) CGColor], (id)[RGB(108, 0, 120) CGColor], nil];
[self.layer insertSublayer:gradient atIndex:0];

我想添加一个内部阴影效果,但我不太确定如何做到这一点。我想我会被要求在drawRect中绘制,但是这会在其他UIView对象上添加图层,因为它应该是一些按钮后面的一个栏,所以我不知所措?

我可以添加另一个层,但同样,不确定如何实现内部阴影效果(如下所示:

感谢你的帮助。

EN

回答 17

Stack Overflow用户

回答已采纳

发布于 2011-04-05 01:30:48

对于任何其他想知道如何按照Costique的建议使用核心图形绘制内部阴影的人,那么这是如何:(在iOS上根据需要调整)

在您的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);

因此,本质上有以下步骤:

  1. Create your path
  2. 设置您想要的填充颜色,将此路径添加到上下文中,并填充上下文
  3. 现在创建一个可以绑定可见路径的更大矩形。在关闭此路径之前,请添加可见路径。然后关闭路径,以便创建一个从中减去可见路径的形状。您可能想要研究填充方法(偶数/奇数的非零缠绕),这取决于您如何创建这些路径。颜色并不重要,因为如果你做的每件事都是正确的,你将看不到这种颜色,只会看到阴影。
票数 110
EN

Stack Overflow用户

发布于 2012-07-11 23:55:19

我知道我来晚了,但这会帮助我在旅途中发现...

值得肯定的是,这本质上是Daniel Thorpe对Costique从较大区域中减去较小区域的解决方案的阐述的修改。此版本适用于使用图层组合而不是覆盖-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];

在这一点上,如果您的父层没有遮罩到其边界,您将看到遮罩层的额外区域周围的层的边缘。如果你只是直接复制这个例子,这将是42个像素的黑色。要摆脱它,你可以简单地使用另一个具有相同路径的CAShapeLayer,并将其设置为阴影层的蒙版:

CAShapeLayer *maskLayer = [CAShapeLayer layer];
[maskLayer setPath:someInnerPath];
[shadowLayer setMask:maskLayer];

我自己没有对此进行基准测试,但我怀疑将此方法与光栅化结合使用会比覆盖-drawRect:更有效。

票数 48
EN

Stack Overflow用户

发布于 2010-12-14 01:23:39

可以使用Core Graphics绘制内部阴影,方法是在边界外创建一个大的矩形路径,减去边界大小的矩形路径,并在生成的路径上填充“正常”阴影。

但是,由于您需要将其与渐变层相结合,我认为一个更简单的解决方案是创建一个内部阴影的9部分透明PNG图像,并将其拉伸到合适的大小。由9部分组成的阴影图像将如下所示(其大小为21x21像素):

CALayer *innerShadowLayer = [CALayer layer];
innerShadowLayer.contents = (id)[UIImage imageNamed: @"innershadow.png"].CGImage;
innerShadowLayer.contentsCenter = CGRectMake(10.0f/21.0f, 10.0f/21.0f, 1.0f/21.0f, 1.0f/21.0f);

然后设置innerShadowLayer的帧,它应该正确地拉伸阴影。

票数 35
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4431292

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档