Почему masksToBounds = YES предотвращает тень CALayer?
Со следующим фрагментом я добавляю эффект тени для одного моего UIView. Это работает очень хорошо. Но как только я установил свойство masksToBounds в представление YES. Эффект теневой тени больше не отображается.
self.myView.layer.shadowColor = [[UIColor blackColor] CGColor];
self.myView.layer.shadowOpacity = 1.0;
self.myView.layer.shadowRadius = 10.0;
self.myView.layer.shadowOffset = CGSizeMake(0.0f, 0.0f);
self.myView.layer.cornerRadius = 5.0;
self.myView.layer.masksToBounds = YES; // <-- This is causing the Drop shadow to not be rendered
UIBezierPath *path = [UIBezierPath bezierPathWithCurvedShadowForRect:self.myView.bounds];
self.myView.layer.shadowPath = path.CGPath;
self.myView.layer.shouldRasterize = YES;
У вас есть идеи по этому поводу?
Ответы
Ответ 1
Поскольку тень - это эффект, сделанный вне представления, и что masksToBounds, установленный в YES, скажет UIView не рисовать что-либо вне себя.
Если вы хотите просмотреть roundedCorner с тенью, я предлагаю вам сделать это с помощью двух видов:
UIView *view1 = [[UIView alloc] init];
UIView *view2 = [[UIView alloc] init];
view1.layer.cornerRadius = 5.0;
view1.layer.masksToBounds = YES;
view2.layer.cornerRadius = 5.0;
view2.layer.shadowColor = [[UIColor blackColor] CGColor];
view2.layer.shadowOpacity = 1.0;
view2.layer.shadowRadius = 10.0;
view2.layer.shadowOffset = CGSizeMake(0.0f, 0.0f);
[view2 addSubview:view1];
[view1 release];
Ответ 2
Теперь это iOS 6, все могло измениться. Ответ TheSquad не работает для меня, пока мне не удалось добавить еще одну строку view2.layer.masksToBounds = NO;
, иначе тень не будет отображаться. Хотя документация говорит, что masksToBounds
НЕТ по умолчанию, мой код показывает обратное.
Вот как я делаю закругленную угловую кнопку с тенью, которая является одним из наиболее часто используемых фрагментов кода в моем приложении.
button.layer.masksToBounds = YES;
button.layer.cornerRadius = 10.0f;
view.layer.masksToBounds = NO; // critical to add this line
view.layer.cornerRadius = 10.0f;
view.layer.shadowOpacity = 1.0f;
// set shadow path to prevent horrible performance
view.layer.shadowPath =
[UIBezierPath bezierPathWithRoundedRect:_button.bounds cornerRadius:10.0f].CGPath;
[view addSubview:button];
ИЗМЕНИТЬ
Если представления должны быть анимированы или прокручиваться, masksToBounds = YES
налоговая производительность значительно, что означает, что анимация, вероятно, будет заикаться. Чтобы получить закругленный угол и тень И плавная анимация или прокрутка, используйте вместо этого следующий код:
button.backgroundColor = [UIColor clearColor];
button.layer.backgroundColor = [UIColor redColor].CGColor;
button.layer.masksToBounds = NO;
button.layer.cornerRadius = 10.0f;
view.layer.shadowOpacity = 0.5f;
view.layer.shadowPath = [UIBezierPath bezierPathWithRoundedRect:_button.bounds cornerRadius:10.0f].CGPath;
view.layer.shadowOffset = CGSizeMake(0.0f, 4.0f);
view.layer.shadowRadius = 2.0f;
view.layer.masksToBounds = NO;
view.layer.cornerRadius = 10.0f;
[view addSubview:button];
Ответ 3
Это версия Swift 3 и IBDesignable ответа, отправленного @TheSquad.
Я использовал ту же концепцию, внося изменения в файл раскадровки. Сначала я переместил свой targetView (тот, который требует углового радиуса и тени) внутри нового контейнера контейнера. Затем я добавил следующие строки кода (Reference: fooobar.com/questions/74200/...), чтобы добавить некоторые атрибуты IBDesignable для класса UIView:
@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
}
}
/* The corner radius of the view. */
@IBInspectable var cornerRadius: CGFloat {
set {
layer.cornerRadius = newValue
}
get {
return layer.cornerRadius
}
}
После добавления этого кода я вернулся к раскадровке и, выбрав мой контейнерный вид, теперь могу найти новый набор атрибутов в инспекторе атрибутов:
![введите описание изображения здесь]()
Помимо добавления значений для этих атрибутов по моему выбору, я также добавил радиус угла в мой targetView и установил свойство masksToBounds как true.
Надеюсь, это поможет:)
Ответ 4
У меня также были резкие проблемы с производительностью с тенями и закругленными углами. Вместо использования части shadowPath я использовал следующие строки, которые отлично решали производительность:
self.layer.shouldRasterize = YES;
self.layer.rasterizationScale = UIScreen.mainScreen.scale;
Ответ 5
версия Swift 3.0 со StoryBoard
Та же идея с @TheSquad. Создайте новое представление под фактическим представлением и добавьте тень в нижний вид.
1. Создайте представление под фактическим представлением
Перетащите UIView
в StoryBoard с тем же ограничением, что и ваш целевой вид. Проверьте клип для привязки к целевому виду. Также убедитесь, что новое представление указано перед целевым представлением, так что целевое представление будет охватывать новое представление.
![введите описание изображения здесь]()
2. Теперь привяжите новое представление к вашему коду, добавьте тень на него
Это просто образец. Вы можете делать все, что хотите здесь.
shadowView.layer.masksToBounds = false
shadowView.layer.shadowColor = UIColor.red.cgColor
shadowView.layer.shadowOpacity = 0.5
shadowView.layer.shadowOffset = CGSize(width: -1, height: 1)
shadowView.layer.shadowRadius = 3
shadowView.layer.shadowPath = UIBezierPath(rect: coverImage.bounds).cgPath
shadowView.layer.shouldRasterize = true
Ответ 6
Вот одно из решений:
@IBOutlet private weak var blockView: UIView! {
didSet {
blockView.backgroundColor = UIColor.white
blockView.layer.shadowColor = UIColor.black.cgColor
blockView.layer.shadowOpacity = 0.5
blockView.layer.shadowOffset = CGSize.zero
blockView.layer.cornerRadius = 10
}
}
@IBOutlet private weak var imageView: UIImageView! {
didSet {
imageView.layer.cornerRadius = 10
imageView.layer.masksToBounds = true
imageView.layer.shouldRasterize = true
}
}
![введите описание изображения здесь]()