为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

米脂 2019-10-04 16:13:31
我有以下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对象的顶部添加该层,因为它应该是某些按钮后面的一个栏,所以我无所适从?我可以添加另一层,但是同样,不确定如何实现内部阴影效果(如下所示:帮助赞赏...
查看完整描述

3 回答

?
绝地无双

TA贡献1946条经验 获得超4个赞

对于任何其他想知道如何根据Costique建议使用Core Graphics绘制内部阴影的人,这就是如何:(在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);

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


创建你的道路

设置所需的填充颜色,将此路径添加到上下文中,然后填充上下文

现在创建一个更大的矩形,可以绑定可见路径。在关闭此路径之前,请添加可见路径。然后关闭路径,以便创建一个形状,其中减去了可见路径。您可能要研究填充方法(偶数/奇数的非零缠绕),具体取决于创建这些路径的方式。本质上,要使子路径在将它们添加在一起时“减去”,您需要沿相反的方向(一个顺时针方向,另一个逆时针方向)绘制(或构造)它们。

然后,您需要将可见路径设置为上下文上的剪切路径,以免在屏幕外绘制任何内容。

然后在上下文上设置阴影,包括阴影,模糊和颜色。

然后在大形状中填充孔。颜色无关紧要,因为如果您正确完成所有操作,就不会看到此颜色,而只会看到阴影。


查看完整回答
反对 回复 2019-10-04
?
拉风的咖菲猫

TA贡献1995条经验 获得超2个赞

我知道我参加这个聚会迟到了,但这本可以帮助我在旅途中尽早找到...


为了在信用到期的地方提供信用,这本质上是对丹尼尔·索普(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:。


查看完整回答
反对 回复 2019-10-04
  • 3 回答
  • 0 关注
  • 1180 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信