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];