圆特定的角并仅在特定的边上显示阴影

Round specific corners of and show shadow on specific sides only

我有以下代码来仅圆化视图的特定角:

- (void)roundOnlySpecifiedCornersInView:(UIView *)view corners:(UIRectCorner)corners
{
    UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:view.bounds byRoundingCorners:(corners) cornerRadii:CGSizeMake(4.0, 4.0)];
    CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];

    maskLayer.path  = maskPath.CGPath;
    view.layer.mask = maskLayer;
}

这可以完美地独立运行。现在我也想要阴影在我的视野中,但我特别想在不同的情况下应用阴影:

我遇到的所有技术都是通过创建视图的插图来工作的。这个问题是,假设你只想在 left/right 边保留阴影,你会偏移底部和顶部。由于 Rect 现在不那么高了,左右的阴影不会覆盖视图的整个高度。另外,用于圆角的遮罩层导致阴影不再出现。

示例代码:

    innerView.layer.shadowColor = [[UIColor colorWithWhite:0.0f alpha:0.1f] CGColor];
    innerView.layer.shadowOpacity = 1.0f;
    innerView.layer.shadowOffset = CGSizeMake(0.0f, 0.0f);
    innerView.layer.shadowRadius = 6.0f;

    CGRect shadowFrame = UIEdgeInsetsInsetRect(innerView.bounds, UIEdgeInsetsMake(9, 0, 9, 0));
    CGPathRef shadowPath = [UIBezierPath bezierPathWithRect:shadowFrame].CGPath;

    innerView.layer.shadowPath = shadowPath;

如何在视图中圆化特定的角并同时仅在指定的边显示阴影?

也感谢 Swift 中的回答!

我想要的截图(这个很简单,因为所有的角都需要圆角,所以我可以使用 .layer.cornerRadius 并且它的所有边都有阴影):

现在我只想圆角的两个角(左上角和右上角,左下角和右下角)并只在一些边上添加阴影。

不知道能不能满足你的需求。该代码创建了一个带有顶部和底部阴影以及所有圆角的图像,您可以修改代码来实现您所需要的。你可以用图片作为你cell的背景(好像是UITableViewCell)

如果它不适合你,请告诉我。

图片:

// create a shadow image
CGSize size = CGSizeMake(ScreenWidth, ScreenWidth);
UIGraphicsBeginImageContextWithOptions(size, NO, 0);
CGContextRef context = UIGraphicsGetCurrentContext();

UIColor *backgroundColor = [UIColor colorWithRed:246.0/255.0 green:246.0/255.0 blue:246.0/255.0 alpha:1.0];
UIColor *fillColor = [UIColor whiteColor];
CGRect rect = CGRectMake(10, 10, 100, 44);

// re-draw the background
CGContextSetFillColorWithColor(context, backgroundColor.CGColor);
CGContextFillRect(context, CGRectMake(0, 0, size.width, size.height));

// set top and bottom shadow
CGRect rectTop = CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, 5);
CGContextSaveGState(context);
CGContextSetShadowWithColor(context, CGSizeMake(0, -5), 5, [UIColor colorWithRed:0 green:0 blue:0 alpha:0.1].CGColor);
CGContextSetFillColorWithColor(context, [UIColor redColor].CGColor);
CGContextFillRect(context, rectTop);
CGContextRestoreGState(context);

CGRect rectBottom = CGRectMake(rect.origin.x, rect.origin.y+rect.size.height-5, rect.size.width, 5);
CGContextSaveGState(context);
CGContextSetShadowWithColor(context, CGSizeMake(0, 5), 5, [UIColor colorWithRed:0 green:0 blue:0 alpha:0.1].CGColor);
CGContextSetFillColorWithColor(context, [UIColor redColor].CGColor);
CGContextFillRect(context, rectBottom);
CGContextRestoreGState(context);

// re-draw the background
CGContextSetFillColorWithColor(context, backgroundColor.CGColor);
CGContextFillRect(context, rect);

CGContextSaveGState(context);
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:rect byRoundingCorners:UIRectCornerAllCorners cornerRadii:CGSizeMake(4.0, 4.0)];
[maskPath addClip];
CGContextSetFillColorWithColor(context, fillColor.CGColor);
CGContextFillRect(context, rect);
CGContextRestoreGState(context);

您可以修改代码以获得左上阴影:

// create a shadow image
CGSize size = CGSizeMake(ScreenWidth, ScreenWidth);
UIGraphicsBeginImageContextWithOptions(size, NO, 0);
CGContextRef context = UIGraphicsGetCurrentContext();

UIColor *backgroundColor = [UIColor colorWithRed:246.0/255.0 green:246.0/255.0 blue:246.0/255.0 alpha:1.0];
UIColor *fillColor = [UIColor whiteColor];
CGRect rect = CGRectMake(10, 10, 100, 44);

// re-draw the background
CGContextSetFillColorWithColor(context, backgroundColor.CGColor);
CGContextFillRect(context, CGRectMake(0, 0, size.width, size.height));

// set top and left shadow
CGRect rectTop = CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, 5);
CGContextSaveGState(context);
CGContextSetShadowWithColor(context, CGSizeMake(0, -5), 5, [UIColor colorWithRed:0 green:0 blue:0 alpha:0.1].CGColor);
CGContextSetFillColorWithColor(context, [UIColor redColor].CGColor);
CGContextFillRect(context, rectTop);
CGContextRestoreGState(context);

CGRect rectLeft = CGRectMake(rect.origin.x, rect.origin.y, 5, rect.size.height);
CGContextSaveGState(context);
CGContextSetShadowWithColor(context, CGSizeMake(-5, 0), 5, [UIColor colorWithRed:0 green:0 blue:0 alpha:0.1].CGColor);
CGContextSetFillColorWithColor(context, [UIColor redColor].CGColor);
CGContextFillRect(context, rectLeft);
CGContextRestoreGState(context);

// re-draw the background
CGContextSetFillColorWithColor(context, backgroundColor.CGColor);
CGContextFillRect(context, rect);

CGContextSaveGState(context);
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:rect byRoundingCorners:UIRectCornerAllCorners cornerRadii:CGSizeMake(4.0, 4.0)];
[maskPath addClip];
CGContextSetFillColorWithColor(context, fillColor.CGColor);
CGContextFillRect(context, rect);
CGContextRestoreGState(context);

HTH

对于特定的角设置角半径

参考自:how to set cornerRadius for only top-left and top-right corner of a UIView?

UIBezierPath *maskPath;
maskPath = [UIBezierPathbezierPathWithRoundedRect:_backgroundImageView.bounds 
                             byRoundingCorners:(UIRectCornerBottomLeft|UIRectCornerBottomRight) 
                                   cornerRadii:CGSizeMake(3.0, 3.0)];

CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
maskLayer.frame = self.bounds;
maskLayer.path = maskPath.CGPath;
_imageView.layer.mask = maskLayer;
[maskLayer release];

当然,在很多很多情况下,您会希望通过绘制阴影来实现这一点。但是,您可以考虑以下方法:使用 可拉伸图像 ,阴影就在您需要的两侧,例如类似的东西(虽然这个四面都有阴影):

就在你说:“Ewwwww!他正在使用图像来制作简单的阴影!”让我强调一下,这在性能方面会更好。例如,如果 UICollectionView 中有很多单元格并且每个单元格都在重新绘制其阴影,则它可能会在滚动期间显着降低您的应用程序的速度,而对于基于图像的阴影,它基本上是相同的.

我会走得更远,建议您实际上也可以使用可拉伸图像来用圆角遮盖视图!现在,这看起来有点过头了,但如果您注意到性能急剧下降,我会试一试。您基本上需要做的是准备另一个可拉伸图像,该图像具有透明 "middle" 部分和与背景颜色相同的圆角。类似于:

再说一次,在你对这种用两行代码就可以轻松实现的奇怪方式投反对票之前...

view.layer.cornerRadius = 20
view.layer.masksToBounds = true

...让我指出,当您必须同时显示一堆被屏蔽的视图时,这将 荒谬地 更快地工作:例如,屏蔽 UICollectionViewCell秒。基本上,如果你在 UIView 的图层上设置了一个蒙版,这个蒙版将被重新计算并实时应用,这会在 [=] 的频繁重绘期间在性能方面花费你很多13=] 内容 — 例如,滚动 UITableViewUICollectionView 时。

显然,如果您的背景不是纯色,例如有渐变,这将不起作用。但是,在许多其他情况下,这可能会帮助您实现更流畅的 UI 性能。在您的特定情况下,另一个优势是您可以轻松控制要遮盖的角以及阴影应该放置的位置。

同样,我并不是在暗示在每种情况下都是这样。我要说的是,在很多情况下这可以帮助显着提高性能:例如,如果您屏蔽了太多同时在屏幕上呈现的视图,并且布局预计经常重绘。