UIView shadow и InterfaceBuilder
Я хочу добавить тень с использованием CALayer в представление пользовательского интерфейса (изображения).
Следующий код работает в целом отлично
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
Я не уверен, в чем проблема: убедитесь, что для вашего свойства UIImageView
clipsToBounds
установлено значение NO
. Вы можете сделать это в viewDidLoad
после загрузки из файла nib путем ссылки на ваш IBOutlet. Вам не нужно обертывать его в другое представление.
Edit
В свете того, что вам нужно масштабировать изображение, используя аспект заполнения, вы можете использовать свойство 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 contentsRect property in order to 'clip' the image to the image view 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
в качестве параметра.
Надеюсь, это поможет.
Ответ 2
Добавьте в проект файл 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 для каждого вида в панели "Утилиты" > "Attributes Inspector":
![Панель Утилиты]()
Теперь вы можете легко установить тень.
Примечания:
- Тень появится только во время выполнения.
- clipsToBounds
должно быть ложным (по умолчанию оно)
Ответ 3
Я знаю, что этот вопрос длинный, но в последнее время я был в подобной ситуации, поэтому я решил поставить свой ответ для тех, кто находится в такой ситуации.
Я хотел иметь возможность устанавливать borderColor
и shadowColor
на UIView
через построитель интерфейсов, но тип свойства borderColor
borderColor
- тип CGColor
), который не является одним из типов, разрешенных для изменения в пользовательской функции атрибутов времени выполнения.
Итак, я сделал расширение для CALayer
, и я добавил два свойства, называемые borderColorIB и shadowColorIB, которые имеют тип UIColor:
RuntimeAttributes.h
@import QuartzCore;
@interface CALayer (IBConfiguration)
@property(nonatomic, assign) UIColor* borderColorIB;
@property(nonatomic, assign) UIColor* shadowColorIB;
@end
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
Теперь я могу установить эти два свойства через Interface Builder следующим образом:
Вот изображение, чтобы показать вам, как я это сделал:
![enter image description here]()
... и результат будет проявляться во время выполнения, а не в Xcode:
![enter image description here]()
Надеюсь, это поможет некоторым людям!