28

我试图在图像上绘制阴影和角落半径。我可以单独添加它们,但我无法同时添加两种效果。我添加了一个阴影:无法添加角落半径和阴影

[layer setShadowOffset:CGSizeMake(0, 3)]; 
[layer setShadowOpacity:0.4]; 
[layer setShadowRadius:3.0f]; 
[layer setShouldRasterize:YES]; 

这里,图层是UIView子类的CALayer。所以这个作品时,我设置

[layer setMasksToBounds:NO]; 

现在增加一个圆角半径我这样做:

[layer setCornerRadius:7.0f]; 

,但我需要设置MasksToBounds为是为了这个工作:

[layer setMasksToBounds:YES]; 

无论如何我可以得到这两个效果添加?

感谢您的时间,

丹尼斯

回答

57

是的,是有...

如果要同时具有拐角半径和阴影,你不打开- masksToBounds,而是设置圆角半径,并用圆角矩形设置阴影的贝塞尔路径。保持两个相同的半径:

[layer setShadowOffset:CGSizeMake(0, 3)]; 
[layer setShadowOpacity:0.4]; 
[layer setShadowRadius:3.0f]; 
[layer setShouldRasterize:YES]; 

[layer setCornerRadius:12.0f]; 
[layer setShadowPath: 
        [[UIBezierPath bezierPathWithRoundedRect:[self bounds] 
               cornerRadius:12.0f] CGPath]]; 

您可能希望在不一旦你设置阴影路径设置-shouldRasterize参数来检查你的表现。一旦你设置了阴影路径,绘图性能就会非常好。

UPDATE

我还没有看这个问题很长一段时间,但现在看来,你不再需要设置一个shadowPath为了得到这个工作。只需设置cornerRadiusshadowOpacity即可使用。我认为iOS5以后就是这样(据我所知)。提供此更新可能是不必要的,因为设置这些参数“正常”,但我将为后人提供它。总括来说,这是现在所有你需要:

[layer setShadowOpacity:0.4]; 
[layer setCornerRadius:12.0f]; 

如果您仍需要更好的性能,你可以继续设置shouldRasterize参数,以及:

[layer setShouldRasterize:YES]; 

和性能来讲,它的价值注意到如果你注意到呆滞的动画,你会希望使用设置阴影路径的技巧。此更新实际上只是指出,设置路径不再需要达到同时显示拐角半径和阴影的效果。但是,如果性能是您的首要任务,请使用路径。

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    CALayer *layer = [CALayer layer]; 
    [layer setBounds:CGRectMake(0.0f, 0.0f, 100.0f, 200.0f)]; 
    [layer setPosition:[[self view] center]]; 
    [layer setBackgroundColor:[[UIColor lightGrayColor] CGColor]]; 
    [layer setShadowOpacity:0.55f]; 
    [layer setCornerRadius:8.0f]; 
    [layer setBorderWidth:1.0f]; 

    [[[self view] layer] addSublayer:layer]; 

    [[[self testView] layer] setShadowOpacity:0.55f]; 
    [[[self testView] layer] setShadowRadius:15.0f]; 
    [[[self testView] layer] setCornerRadius:8.0f]; 
    [[[self testView] layer] setBorderWidth:1.0f]; 
} 

更新2

由于人们似乎遇到了麻烦这在某些情况下工作,我在这里从我创建了一个样本项目后更完整的代码片段

testView是我在界面生成器中添加的一个UIView,并设置了一个插座。这是为了确保它在明确添加的两个图层以及子视图中的图层上都一样。

我已经在iOS5到iOS6.1的模拟器上测试了这个。它给出了这样的结果,我在他们每个人:

enter image description here

+1

有什么理由不shouldRasterize设置为YES? – memmons 2010-11-09 02:50:53

+2

这取决于你更新图层的频率。如果您打算将其设置一次,而不是再次更新,则栅格化它会有助于提升性能,前提是您正在为图层制作动画。但是,如果图层的内容经常更新,每次内容更改时都会将该内容呈现为图像,这实际上会损害您的滚动性能(假设您正在滚动/制作动画)。 – 2010-11-09 04:44:29

+0

需要UIBezierPath和bezierPathWithRoundedRect之间的空格。 – 2011-01-29 03:13:36

-2
view.layer.cornerRadius=4; 
[view.layer setMasksToBounds:YES]; 
[view.layer setShadowColor:SHADOW_COLOR]; 
[view.layer setShadowOpacity:4 ]; 
[view.layer setShadowRadius:4]; 
[view.layer setShadowOffset:0];  
[view.layer setShadowPath: [[UIBezierPath bezierPathWithRoundedRect:[view bounds] cornerRadius:CORNER_RADIUS] CGPath]]; 
view.layer.borderColor=[[UIColor lightGrayColor] colorWithAlphaComponent:.5].CGColor; 
view.layer.borderWidth=.4; 
+2

可怕。不管用。 – Liam 2014-06-19 08:35:08

3

以下斯威夫特3的代码演示了如何使用CAShapeLayerCALayer绘制的图像上的阴影和圆角半径。

import UIKit 

class ViewController: UIViewController { 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     // constants 
     let radius: CGFloat = 20, offset = 8 
     let rect = CGRect(x: 0, y: 0, width: 200, height: 200) 

     // roundedView 
     let roundedView = UIView() 
     view.addSubview(roundedView) 

     // shadow layer 
     let shadowLayer = CALayer() 
     shadowLayer.shadowColor = UIColor.darkGray.cgColor 
     shadowLayer.shadowPath = UIBezierPath(roundedRect: rect, cornerRadius: radius).cgPath 
     shadowLayer.shadowOffset = CGSize(width: offset, height: offset) 
     shadowLayer.shadowOpacity = 0.8 
     shadowLayer.shadowRadius = 2 
     roundedView.layer.addSublayer(shadowLayer) 

     // mask layer 
     let maskLayer = CAShapeLayer() 
     maskLayer.path = UIBezierPath(roundedRect: rect, cornerRadius: radius).cgPath 

     // image layer 
     let imageLayer = CALayer() 
     imageLayer.mask = maskLayer 
     imageLayer.frame = rect 
     imageLayer.contentsGravity = kCAGravityResizeAspectFill 
     imageLayer.contents = UIImage(named: "image")?.cgImage 
     roundedView.layer.addSublayer(imageLayer) 

     // auto layout 
     roundedView.translatesAutoresizingMaskIntoConstraints = false 
     roundedView.widthAnchor.constraint(equalToConstant: rect.width).isActive = true 
     roundedView.heightAnchor.constraint(equalToConstant: rect.height).isActive = true 
     roundedView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true 
     roundedView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true 
    } 

} 

此代码生成以下显示:

enter image description here


前面的代码能够被重构到以下迅速文件:

CustomView.swift

import UIKit 

class CustomView: UIView { 

    var imageLayer: CALayer! 
    var image: UIImage? { 
     didSet { refreshImage() } 
    } 

    override var intrinsicContentSize: 


     CGSize { 
     return CGSize(width: 200, height: 200) 
    } 

    func refreshImage() { 
     if let imageLayer = imageLayer, let image = image { 
      imageLayer.contents = image.cgImage 
     } 
    } 

    override func layoutSubviews() { 
     super.layoutSubviews() 

     if imageLayer == nil { 
      let radius: CGFloat = 20, offset: CGFloat = 8 

      let shadowLayer = CALayer() 
      shadowLayer.shadowColor = UIColor.darkGray.cgColor 
      shadowLayer.shadowPath = UIBezierPath(roundedRect: bounds, cornerRadius: radius).cgPath 
      shadowLayer.shadowOffset = CGSize(width: offset, height: offset) 
      shadowLayer.shadowOpacity = 0.8 
      shadowLayer.shadowRadius = 2 
      layer.addSublayer(shadowLayer) 

      let maskLayer = CAShapeLayer() 
      maskLayer.path = UIBezierPath(roundedRect: bounds, cornerRadius: radius).cgPath 

      imageLayer = CALayer() 
      imageLayer.mask = maskLayer 
      imageLayer.frame = bounds 
      imageLayer.backgroundColor = UIColor.red.cgColor 
      imageLayer.contentsGravity = kCAGravityResizeAspectFill 
      layer.addSublayer(imageLayer) 
     } 


     refreshImage() 
    } 

} 

ViewController.swift

import UIKit 

class ViewController: UIViewController { 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     let roundedView = CustomView() 
     roundedView.translatesAutoresizingMaskIntoConstraints = false 
     view.addSubview(roundedView) 

     // auto layout 
     let horizontalConstraint = roundedView.centerXAnchor.constraint(equalTo: view.centerXAnchor) 
     let verticalConstraint = roundedView.centerYAnchor.constraint(equalTo: view.centerYAnchor) 
     NSLayoutConstraint.activate([horizontalConstraint, verticalConstraint]) 

     roundedView.image = UIImage(named: "image") 
    } 

} 

你可以找到更多的途径来对这个Github repo圆角和阴影图像组合。

2

因为我使用背景图像UIButton没有这些答案为我工作。我的按钮不断收到阴影或没有圆边。

在我的情况下,最简单的方法是只需添加另一种观点认为后面的按钮和阴影添加到它,像这样:

button.clipsToBounds=YES; 
button.layer.cornerRadius = 25; 

UIView *shadowView = [[UIView alloc]initWithFrame:button.frame]; 

shadowView.backgroundColor = [UIColor whiteColor];//needs this to cast shadow 
shadowView.layer.cornerRadius = 25; 
shadowView.clipsToBounds = YES; 
shadowView.layer.masksToBounds = NO; 
shadowView.layer.shadowOffset = CGSizeMake(0, 2); 
shadowView.layer.shadowRadius = 1; 
shadowView.layer.shadowOpacity = 0.2; 


[[button superview]addSubview:shadowView]; 
[[button superview]bringSubviewToFront:button];