Не могу добавить угловой радиус и тень - PullRequest
32 голосов
/ 23 июля 2010

Я пытаюсь нарисовать тень и угловой радиус на изображении. Я могу добавить их отдельно, но у меня нет способа добавить оба эффекта одновременно. Я добавляю тень с:

[layer setShadowOffset:CGSizeMake(0, 3)];
[layer setShadowOpacity:0.4];
[layer setShadowRadius:3.0f];
[layer setShouldRasterize:YES];

Здесь layer - это CALayer подкласса UIView. Так что это работает всякий раз, когда я устанавливаю

[layer setMasksToBounds:NO];

Теперь, чтобы добавить угловой радиус, я делаю это:

[layer setCornerRadius:7.0f];

но мне нужно установить для MasksToBounds значение YES, чтобы это работало:

[layer setMasksToBounds:YES];

Можно ли как-нибудь добавить оба этих эффекта?

Спасибо за ваше время,

Денис

Ответы [ 4 ]

59 голосов
/ 24 июля 2010

Да, да, есть ...

Если вам нужны и угловой радиус, и тень, вы не включаете -masksToBounds , а устанавливаете угловой радиуси установите безье путь тени с закругленным прямоугольником.Держите радиус обоих одинаковым:

[layer setShadowOffset:CGSizeMake(0, 3)];
[layer setShadowOpacity:0.4];
[layer setShadowRadius:3.0f];
[layer setShouldRasterize:YES];

[layer setCornerRadius:12.0f];
[layer setShadowPath:
                   [[UIBezierPath bezierPathWithRoundedRect:[self bounds]
                                               cornerRadius:12.0f] CGPath]];

Возможно, вы захотите проверить свою производительность без набора параметра -shouldRasterize , как только вы установите путь тени.Производительность рисования имеет тенденцию быть очень хорошей, если вы задали путь тени.

ОБНОВЛЕНИЕ

Я не рассматривал эту проблему довольно давно, но, похоже,что вам больше не нужно устанавливать shadowPath, чтобы заставить это работать.Простая установка cornerRadius и shadowOpacity будет работать сейчас.Я думаю, что это имело место с iOS5 (насколько я могу судить).Предоставление этого обновления, вероятно, не является необходимым, поскольку установка этих параметров «просто работает», но я предоставлю это для потомков.Напомним, что теперь это все, что вам нужно:

[layer setShadowOpacity:0.4];
[layer setCornerRadius:12.0f];

Если вам все еще нужна лучшая производительность, вы можете также установить параметр shouldRasterize:

[layer setShouldRasterize:YES];

ИГоворя о производительности, стоит отметить, что если вы замечаете вялую анимацию, вам все-таки захочется использовать технику установки пути тени.Это обновление действительно было просто для того, чтобы указать, что установка пути больше не требуется для достижения эффекта одновременного отображения углового радиуса и тени.Если производительность является вашим приоритетом, используйте путь.

ОБНОВЛЕНИЕ 2

Поскольку у людей, похоже, возникают проблемы с тем, чтобы заставить это работать в некоторых случаях, я будуопубликуйте более полный фрагмент кода здесь из примера проекта, который я создал:

- (void)viewDidLoad
{
  [super viewDidLoad];

  CALayer *layer = [CALayer layer];
  [layer setBounds:CGRectMake(0.0f, 0.0f, 100.0f, 200.0f)];
  [layer setPosition:[[self view] center]];
  [layer setBackgroundColor:[[UIColor lightGrayColor] CGColor]];
  [layer setShadowOpacity:0.55f];
  [layer setCornerRadius:8.0f];
  [layer setBorderWidth:1.0f];

  [[[self view] layer] addSublayer:layer];

  [[[self testView] layer] setShadowOpacity:0.55f];
  [[[self testView] layer] setShadowRadius:15.0f];
  [[[self testView] layer] setCornerRadius:8.0f];
  [[[self testView] layer] setBorderWidth:1.0f];
}

testView - это UIView, который я добавил в Interface Builder и включил выход.Это сделано для того, чтобы убедиться, что он работает одинаково на обоих слоях, которые вы добавляете явно, а также на слоях в подпредставлениях.

Я проверял это на симуляторах для iOS5 - iOS6.1.Это дает мне результат в каждом из них:

enter image description here

3 голосов
/ 14 июня 2016

Поскольку я использую UIButton с фоновым изображением, ни один из этих ответов не сработал для меня. Я не получаю ни тени, ни круглых краев на кнопках.

Самый простой способ в моем сценарии состоял в том, чтобы просто добавить другой вид за кнопкой и добавить тень к ней следующим образом:

button.clipsToBounds=YES;
button.layer.cornerRadius = 25;

UIView *shadowView = [[UIView alloc]initWithFrame:button.frame];

shadowView.backgroundColor = [UIColor whiteColor];//needs this to cast shadow
shadowView.layer.cornerRadius = 25;
shadowView.clipsToBounds = YES;
shadowView.layer.masksToBounds = NO;
shadowView.layer.shadowOffset = CGSizeMake(0, 2);
shadowView.layer.shadowRadius = 1;
shadowView.layer.shadowOpacity = 0.2;


[[button superview]addSubview:shadowView];
[[button superview]bringSubviewToFront:button];
3 голосов
/ 03 января 2016

Следующий код Swift 3 показывает, как нарисовать тень и угловой радиус на изображении, используя CAShapeLayer и CALayer.

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // constants
        let radius: CGFloat = 20, offset = 8
        let rect = CGRect(x: 0, y: 0, width: 200, height: 200)

        // roundedView
        let roundedView = UIView()
        view.addSubview(roundedView)

        // shadow layer
        let shadowLayer = CALayer()
        shadowLayer.shadowColor = UIColor.darkGray.cgColor
        shadowLayer.shadowPath = UIBezierPath(roundedRect: rect, cornerRadius: radius).cgPath
        shadowLayer.shadowOffset = CGSize(width: offset, height: offset)
        shadowLayer.shadowOpacity = 0.8
        shadowLayer.shadowRadius = 2
        roundedView.layer.addSublayer(shadowLayer)

        // mask layer
        let maskLayer = CAShapeLayer()
        maskLayer.path = UIBezierPath(roundedRect: rect, cornerRadius: radius).cgPath

        // image layer
        let imageLayer = CALayer()
        imageLayer.mask = maskLayer
        imageLayer.frame = rect
        imageLayer.contentsGravity = kCAGravityResizeAspectFill
        imageLayer.contents = UIImage(named: "image")?.cgImage
        roundedView.layer.addSublayer(imageLayer)

        // auto layout
        roundedView.translatesAutoresizingMaskIntoConstraints = false
        roundedView.widthAnchor.constraint(equalToConstant: rect.width).isActive = true
        roundedView.heightAnchor.constraint(equalToConstant: rect.height).isActive = true
        roundedView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        roundedView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
    }

}

Этот код генерирует следующее отображение:

enter image description here


Предыдущий код может быть преобразован в следующие быстрые файлы:

CustomView.swift

import UIKit

class CustomView: UIView {

    var imageLayer: CALayer!
    var image: UIImage? {
        didSet { refreshImage() }
    }

    override var intrinsicContentSize:


        CGSize {
        return CGSize(width: 200, height: 200)
    }

    func refreshImage() {
        if let imageLayer = imageLayer, let image = image {
            imageLayer.contents = image.cgImage
        }
    }

    override func layoutSubviews() {
        super.layoutSubviews()

        if imageLayer == nil {
            let radius: CGFloat = 20, offset: CGFloat = 8

            let shadowLayer = CALayer()
            shadowLayer.shadowColor = UIColor.darkGray.cgColor
            shadowLayer.shadowPath = UIBezierPath(roundedRect: bounds, cornerRadius: radius).cgPath
            shadowLayer.shadowOffset = CGSize(width: offset, height: offset)
            shadowLayer.shadowOpacity = 0.8
            shadowLayer.shadowRadius = 2
            layer.addSublayer(shadowLayer)

            let maskLayer = CAShapeLayer()
            maskLayer.path = UIBezierPath(roundedRect: bounds, cornerRadius: radius).cgPath

            imageLayer = CALayer()
            imageLayer.mask = maskLayer
            imageLayer.frame = bounds
            imageLayer.backgroundColor = UIColor.red.cgColor
            imageLayer.contentsGravity = kCAGravityResizeAspectFill
            layer.addSublayer(imageLayer)
        }


        refreshImage()
    }

}

ViewController.swift

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let roundedView = CustomView()
        roundedView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(roundedView)

        // auto layout
        let horizontalConstraint = roundedView.centerXAnchor.constraint(equalTo: view.centerXAnchor)
        let verticalConstraint = roundedView.centerYAnchor.constraint(equalTo: view.centerYAnchor)
        NSLayoutConstraint.activate([horizontalConstraint, verticalConstraint])

        roundedView.image = UIImage(named: "image")
    }

}

Вы можете найти больше способов комбинировать изображения с закругленными углами и тенью на этом Github репо .

0 голосов
/ 21 мая 2013
view.layer.cornerRadius=4;
[view.layer setMasksToBounds:YES];
[view.layer setShadowColor:SHADOW_COLOR];
[view.layer setShadowOpacity:4 ];
[view.layer setShadowRadius:4];
[view.layer setShadowOffset:0];    
[view.layer setShadowPath: [[UIBezierPath bezierPathWithRoundedRect:[view bounds] cornerRadius:CORNER_RADIUS] CGPath]];
view.layer.borderColor=[[UIColor lightGrayColor] colorWithAlphaComponent:.5].CGColor;
view.layer.borderWidth=.4;
...