2011-09-20 15 views
13

私は、UI(画像)表示にCALayerのを使用してドロップシャドウを追加したいです。 次のコードは、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ではないようで分かったが、私はYES =私のInterfaceBuilderビューのclipsToBoundsを設定していること(デフォルトでは)falseにする必要があります。ここにNOを置いても問題ありません。だから私は、クリップのToBound = NOと影で2番目のビューでビューをラップする必要がありますね。別の方法がありますか? – Dennis

+0

同じ問題がありましたが、Interface Builderのビューで "Clip Subviews"がチェックされたためです。 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が必要な理由は、画像が大きすぎてビューに収まらないため、「アスペクトの塗りつぶし」を使って見栄えを良くする必要があるということです。私は、もちろん、イメージを完全に新しいものに描画し、次にUIGraphicsGetImageFromCurrentImageContext()を使ってフィッティングを取得することで、イメージ自体を切り抜くことができます。しかし、それは多くのオーバーヘッドではないでしょうか? – Dennis

+0

@Dennis:画像が静的で、そのサイズでしか使用されない場合は、最初に画像編集ソフトウェアで画像を再作成してから、プロジェクトの画像ビューで変更する必要はありませんその幾何学。しかしこれがオプションでない場合は、上記の私の編集を参照してください。 – Stuart

14

私はこの質問が長く持って知っているが、私はこのような状況にある人のための私の答えを置くことを決めたので、最近私は似たような状況にありました。

私はInterface Builderを経由UIViewborderColorshadowColorを設定できるようにしたかったが、層のborderColorプロパティの型がで変更することが許可されたタイプのものではありません(ただshadowColorのように)CGColorされていますユーザー定義のランタイム属性機能

だから私は、CALayerの拡張子を作って、私はタイプUIColorであるborderColorIBとshadowColorIBと呼ばれる2つのプロパティを追加しました:

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でこの2つのプロパティを設定することができる:「ユーザー定義のランタイム属性」セクション(アイデンティティインスペクタ)で

  1. を確認してくださいUIViewを選択し、以下のランタイム属性を追加します

    • layer.borderWidth、数、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

関連する問題