2011-09-20 148 views
13

我想添加一個陰影使用CALayer到UI(圖像)視圖。 下面的代碼工作大致天晴UIView陰影和InterfaceBuilder

previewImage.layer.shadowColor = [[UIColor blackColor] CGColor]; 
previewImage.layer.shadowOffset = CGSizeMake(1.0f, 1.0f); 
previewImage.layer.shadowOpacity = 1.0f; 
previewImage.layer.shadowRadius = 8.0f; 

但是,如果以編程方式創建一個視圖,並將其添加作爲一個子視圖我的主視圖這僅適用。當在InterfaceBuilder中設置該視圖並將其定義爲IBOutlet UIImageView時,這不起作用。沒有陰影出現。 那麼我在這裏錯過了什麼?

+1

很隨意,我只是發現似乎實際問題並沒有被InterfaceBuilder的,但事實上,我把我的InterfaceBuilder視圖的clipsToBounds = YES。沒有在這裏是可以的。所以我想我必須在第二個視圖中用clipToBound = NO和陰影來包裝視圖。有另一種方法嗎? – Dennis

+0

我有同樣的問題,但這是因爲「剪輯子視圖」已在Interface Builder中爲視圖選中。取消選中使CALayer陰影可見。 – azdev

回答

2

我不確定是什麼問題 - 確保您的UIImageViewclipsToBounds屬性設置爲NO。您可以通過引用IBOutlet從nib文件加載後在viewDidLoad中執行此操作。你不需要用另一個視圖來包裝它。

編輯

在你需要圖像使用方面填充被縮放的光,則可以使用UIImageViewcontentsRect屬性的下層爲‘模擬’的中剪輯的內容的效果。 contentsRect在圖層內容(在本例中爲圖像)的單位座標空間中是矩形,它定義了應繪製內容的子矩形。

隨着數學的一點點,我們可以通過攝像畫面尺寸與圖像尺寸(佔縱橫填縮放)比較發現這個矩形:

CGSize imageViewSize = previewImage.size; 
CGSize imageSize = previewImage.image.size; 

// Find the scaling required for the image to fit the image view (as for aspect fill). 
CGFloat imageWidthScale = fabsf(imageViewSize.width/imageSize.width); 
CGFloat imageHeightScale = fabsf(imageViewSize.height/imageSize.height); 
CGFloat imageScale = (imageWidthScale > imageHeightScale) ? imageWidthScale : imageHeightScale; 

// Determine the new image size, after scaling. 
CGSize scaledImageSize = CGSizeApplyAffineTransform(imageSize, CGAffineTransformMakeScale(imageScale, imageScale)); 

// Set the layer's contentsRect property in order to 'clip' the image to the image view's bounds. 
previewImage.layer.contentsRect = CGRectMake(((scaledImageSize.width - imageViewSize.width)/2.0f)/scaledImageSize.width, 
              ((scaledImageSize.height - imageViewSize.height)/2.0f)/scaledImageSize.height, 
              imageViewSize.width/scaledImageSize.width, 
              imageViewSize.height/scaledImageSize.height); 

這樣做,你可以離開clipsToBounds集以NO作爲圖像視圖,但該圖像仍會顯示剪切。如果您完全需要更改圖像視圖大小,將代碼包裝爲以UIImageView作爲參數的方法可能會很方便。

我希望這會有所幫助。

+0

我同意。沒有必要的包裝。只是不要clipToBounds - 因爲陰影超出了界限。 – bandejapaisa

+0

我需要clipToBounds的原因是,該圖像太大而不適合視圖,我需要使用「Aspect Fill」使其看起來不錯。當然,我可以通過全新繪製圖像,然後通過UIGraphicsGetImageFromCurrentImageContext()獲取合適的圖像。但是,這不會是很多開銷嗎? – Dennis

+0

@ Dennis:如果圖像是靜態的並且只能以這種尺寸使用,那麼我的第一個建議是首先在圖像編輯軟件中重新創建圖像,然後在項目的圖像視圖中使用它,而無需更改其幾何形狀。如果這不是一個選項,然而,請參閱我上面的編輯。 – Stuart

14

我知道這個問題已經很久了,但最近我處於類似的情況,所以我決定把我的答案放在那些處於這種情況下的人。

我希望能夠通過Interface Builder來設置一個UIViewborderColorshadowColor,但圖層的borderColor屬性的類型是CGColor(就像shadowColor),這是不是在改變允許的類型之一用戶定義的運行時屬性功能。

所以我提出的擴展爲CALayer,我加入兩個屬性稱爲borderColorIB和shadowColorIB是類型的UIColor的:

RuntimeAttributes.h

@import QuartzCore; 

@interface CALayer (IBConfiguration) 

@property(nonatomic, assign) UIColor* borderColorIB; 
@property(nonatomic, assign) UIColor* shadowColorIB; 

@end 

RuntimeAttributes。米

#import <UIKit/UIKit.h> 
#import "RuntimeAttributes.h" 

@implementation CALayer (IBConfiguration) 

-(void)setBorderColorIB:(UIColor*)color 
{ 
    self.borderColor = color.CGColor; 
} 

-(UIColor*)borderColorIB 
{ 
    return [UIColor colorWithCGColor:self.borderColor]; 
} 

-(void)setShadowColorIB:(UIColor*)color 
{ 
    self.shadowColor = color.CGColor; 
} 

-(UIColor*)shadowColorIB 
{ 
    return [UIColor colorWithCGColor:self.shadowColor]; 
} 

@end 

現在我alredy能夠通過Interface Builder中這樣設置這個兩個屬性:

  1. 在「用戶自定義運行屬性」部分(身份檢查)
  2. 確保選擇UIView,並添加以下運行屬性:

    • layer.borderWidth,Number,1
    • layer.borderColorIB,顏色,someColor <- my custom property to set the borderColor
    • layer.shadowColorIB,顏色,someColor <- my custom property to set the shadowColor
    • layer.shadowOpacity,數字,0.8
    • layer.shadowOffset,大小,{5,5}
    • 層。 cornerRadius,數字,5

這裏是展現你的形象我是如何做到:

enter image description here

...和運行過程中的結果將是顯而易見的,而不是在Xcode:

enter image description here

我希望這可以幫助一些人在那裏!

16

添加一個名爲UIView.swift文件在您的項目(或只是粘貼在任何文件):

import UIKit 

@IBDesignable extension UIView { 

    /* The color of the shadow. Defaults to opaque black. Colors created 
    * from patterns are currently NOT supported. Animatable. */ 
    @IBInspectable var shadowColor: UIColor? { 
     set { 
      layer.shadowColor = newValue!.CGColor 
     } 
     get { 
      if let color = layer.shadowColor { 
       return UIColor(CGColor:color) 
      } 
      else { 
       return nil 
      } 
     } 
    } 

    /* The opacity of the shadow. Defaults to 0. Specifying a value outside the 
    * [0,1] range will give undefined results. Animatable. */ 
    @IBInspectable var shadowOpacity: Float { 
     set { 
      layer.shadowOpacity = newValue 
     } 
     get { 
      return layer.shadowOpacity 
     } 
    } 

    /* The shadow offset. Defaults to (0, -3). Animatable. */ 
    @IBInspectable var shadowOffset: CGPoint { 
     set { 
      layer.shadowOffset = CGSize(width: newValue.x, height: newValue.y) 
     } 
     get { 
      return CGPoint(x: layer.shadowOffset.width, y:layer.shadowOffset.height) 
     } 
    } 

    /* The blur radius used to create the shadow. Defaults to 3. Animatable. */ 
    @IBInspectable var shadowRadius: CGFloat { 
     set { 
      layer.shadowRadius = newValue 
     } 
     get { 
      return layer.shadowRadius 
     } 
    } 
} 

那麼這將是可在Interface Builder的工具面板>在每個視圖屬性檢查器:

Utilities Panel

您可以輕鬆地現在設置的影子。

注:
- 陰影只會出現在運行時。
- clipsToBounds應該是假的(默認情況下它是)