UIView阴影和InterfaceBuilder

Den*_*nis 15 core-graphics interface-builder ios

我想使用CALayer将阴影添加到UI(图像)视图.以下代码通常很好

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

但是,这仅在我以编程方式创建该视图并将其作为子视图添加到主视图时才有效.当在InterfaceBuilder中设置该视图并将其定义为IBOutlet UIImageView时,这不起作用.没有阴影出现.那我在这里错过了什么?

Axe*_*min 23

在项目中添加一个名为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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,这将在Interface Builder中为Utilities面板> Attributes Inspector中的每个视图提供:

公用事业小组

您现在可以轻松设置阴影.

注意:
- 阴影仅在运行时出现.
- clipsToBounds应该是假的(默认情况下是)


mau*_*nde 16

我知道这个问题很长,但最近我处于类似的情况,所以我决定把答案给那些处于这种情况的人.

我希望能够通过Interface Builder 设置borderColorshadowColor使用UIView,但是图层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
Run Code Online (Sandbox Code Playgroud)

RuntimeAttributes.m

#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
Run Code Online (Sandbox Code Playgroud)

现在,我可以通过Interface Builder设置这两个属性,如下所示:

  1. 在"用户定义的运行时属性"部分(身份检查器)
  2. 确保选择了UIView,并添加以下运行时属性:

    • layer.borderWidth,Number,1
    • layer.borderColorIB,Color,someColor <- my custom property to set the borderColor
    • layer.shadowColorIB,Color,someColor <- my custom property to set the shadowColor
    • layer.shadowOpacity,Number,0.8
    • layer.shadowOffset,size,{5,5}
    • layer.cornerRadius,Number,5

这是一张图片,告诉你我是怎么做的:

在此输入图像描述

... ...结果将在运行时显而易见,而不是在Xcode中:

在此输入图像描述

我希望这可以帮助那里的一些人!


Stu*_*art 3

我不确定问题是什么 - 确保您的UIImageView属性clipsToBounds设置为NO. 您可以在viewDidLoad从 nib 文件加载后通过引用 IBOutlet 来执行此操作。您不需要将其包装在另一个视图中。

编辑

鉴于您需要使用宽高比填充来缩放图像,您可以使用contentsRect的底层属性UIImageView来“模拟”内容剪切的效果。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);
Run Code Online (Sandbox Code Playgroud)

执行此操作后,您可以将图像视图保留clipsToBounds设置为NO,但图像仍会显示为被剪裁的。如果您需要更改图像视图大小,则将此代码包装到以 a 作为UIImageView参数的方法中可能会很方便。

我希望这有帮助。