2010-09-11 2 views
76

С помощью следующего фрагмента я добавляю эффект тени для одного моего UIView. Это работает очень хорошо. Но как только я установил вид masksToBounds на ДА. Эффект отбрасывания больше не отображается.Почему masksToBounds = ДА предотвращает тень CALayer?

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; 

У вас есть идеи по этому вопросу?

ответ

152

Поскольку тень является эффектом, выполняемым за пределами представления, и что masksToBounds, установленный в YES, скажет UIView не рисовать что-либо, что находится вне себя.

Если вы хотите вид roundedCorner с тенью, я предлагаю вам сделать это с 2-мя видами:

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]; 
+9

Проклятые! В этом есть смысл! – jchatard

+0

Большое вам спасибо ... Это очень помогло мне. Благодарен вам .. :) – innodeasapps

+0

С удовольствием! – TheSquad

14

Это 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]; 

EDIT

Если взгляды должны быть анимированными или прокручивается, 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]; 
+0

Спасибо за фрагмент, особенно оцените часть shadowPath ... –

+4

+1 для первого ответа. Ваш обновленный ответ не будет работать для закругленных углов. Если вы установите «masksToBounds» на «NO», округлые углы исчезнут. Вместо того, чтобы изменять это, вы можете использовать свойство «shouldRasterize», чтобы получить хорошую производительность. –

1

Я также имел кардинальные проблемы с производительностью тенью и закругленными углами. Вместо того, чтобы использовать часть shadowPath, я использовал следующие строки, которые прекрасно решаемые на падение производительности:

self.layer.shouldRasterize = YES; 
self.layer.rasterizationScale = UIScreen.mainScreen.scale; 
+0

Тем не менее, не может анимировать или ретранслировать экран с этим. –

2

Это Swift 3 и IBDesignable вариант ответа разместил @TheSquad.

Я использовал ту же концепцию, внося изменения в файл раскадровки. Сначала я переместил мой targetView (тот, который требует углового радиуса и тени) внутри нового контейнера View. Затем я добавил следующие строки кода (Reference: https://stackoverflow.com/a/35372901/419192), чтобы добавить некоторые 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 
    } 
} 

После добавления этого кода, я вернулся к раскадровке и о выборе моей containerView теперь я мог найти новый набор атрибутов в инспекторе атрибутов:

enter image description here

Кроме добавления значения для этих атрибутов, как на мой выбор, я также добавил радиус угла к моему targetView и установите для свойства masksToBounds значение true.

Я надеюсь, что это помогает :)

1

Swift версии 3.0 с раскадровкой

Той же идея с @TheSquad. Создайте новое представление под реальным видом и добавьте тень в нижний вид.

1. Создайте представление по фактической точки зрения

Перетащите UIView раскадровку с таким же ограничением, как целевой точки зрения. Проверьте клип для привязки к целевому виду. Также убедитесь, что новое представление указано перед целевым представлением, чтобы целевое представление охватывало новое представление.

enter image description here

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 
0

Вот одно из решений:

 @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 
     } 
     } 

enter image description here

 Смежные вопросы

  • Нет связанных вопросов^_^