Подтвердить что ты не робот

Нарисуйте тень только с трех сторон UIView

Я успешно реализовал рисование тени вокруг моего UIView следующим образом:

block1.layer.masksToBounds = NO;
block1.layer.shadowOffset = CGSizeMake(0, 0);
block1.layer.shadowRadius = 1;
block1.layer.shadowOpacity = 0.7;

Что происходит, у меня есть прямоугольник UIView, и я бы хотел нарисовать тень вокруг него с трех сторон, оставив нижнюю сторону без тени.

Я знаю, что я должен указать block1.layer.shadowPath, создав новый UIBezierPath, но я не уверен, как это сделать.

Очевидно, что установка layer.shadowOffset не сделает трюк для меня.

Спасибо заранее!

4b9b3361

Ответ 1

Я знаю, что вы говорите, что настройка layer.shadowOffset не сработает для вас, но вам разрешено указывать отрицательные значения, поэтому установка layer.shadowOffset = CGSizeMake(0.0, -2.0) будет близка к тому эффекту, который вы ищете, но, конечно, я ожидаю, что вы хотите, чтобы он был даже с трех сторон.

Итак, перейдем к layer.shadowPath!

UIView *block1 = [[UIView alloc] initWithFrame:CGRectMake(32.0, 32.0, 128.0, 128.0)];
[block1 setBackgroundColor:[UIColor orangeColor]];
[self.view addSubview:block1];

block1.layer.masksToBounds = NO;
block1.layer.shadowOffset = CGSizeMake(0, 0);
block1.layer.shadowRadius = 1;
block1.layer.shadowOpacity = 0.7;

UIBezierPath *path = [UIBezierPath bezierPath];

// Start at the Top Left Corner
[path moveToPoint:CGPointMake(0.0, 0.0)];

// Move to the Top Right Corner
[path addLineToPoint:CGPointMake(CGRectGetWidth(block1.frame), 0.0)];

// Move to the Bottom Right Corner
[path addLineToPoint:CGPointMake(CGRectGetWidth(block1.frame), CGRectGetHeight(block1.frame))];

// This is the extra point in the middle :) Its the secret sauce.
[path addLineToPoint:CGPointMake(CGRectGetWidth(block1.frame) / 2.0, CGRectGetHeight(block1.frame) / 2.0)];

// Move to the Bottom Left Corner
[path addLineToPoint:CGPointMake(0.0, CGRectGetHeight(block1.frame))];

// Move to the Close the Path
[path closePath];

block1.layer.shadowPath = path.CGPath;

И чтобы дать вам представление о том, что происходит, вот реальный теневой путь, который вы только что нарисовали:)

enter image description here

Его можно просто сдвинуть эту дополнительную среднюю точку до или после других строк, чтобы выбрать, какая сторона будет опущена.

Ответ 2

Обновление Ryan Poolos Ответ на Swift 3.0

Благодаря Ryan Poolos

class sampleViewController: UIViewController {
    var block1: UIView! = nil

    override func viewDidLoad() {

    super.viewDidLoad()
    block1 = UIView(frame: CGRect(x: 32.0, y: 32.0, width: 128.0, height: 128.0))
    block1.backgroundColor = UIColor.orange
    self.view.addSubview(block1)

    block1.layer.masksToBounds = false
    block1.layer.shadowOffset = CGSize(width: 0.0, height: 0.0)
    block1.layer.shadowRadius = 1.0
    block1.layer.shadowOpacity = 0.7

    let path = UIBezierPath()

    // Start at the Top Left Corner
    path.move(to: CGPoint(x: 0.0, y: 0.0))

    // Move to the Top Right Corner
    path.addLine(to: CGPoint(x: block1.frame.size.width, y: 0.0))

    // Move to the Bottom Right Corner
    path.addLine(to: CGPoint(x: block1.frame.size.width, y: block1.frame.size.height))

    // This is the extra point in the middle :) Its the secret sauce.
    path.addLine(to: CGPoint(x: block1.frame.size.width/2.0, y: block1.frame.size.height/2.0))

    // Move to the Bottom Left Corner
    path.addLine(to: CGPoint(x: 0.0, y: block1.frame.size.height))

    path.close()

    block1.layer.shadowPath = path.cgPath

   }
}

Результат:

введите описание изображения здесь

Ответ 3

Несколько улучшений для других ответов, благодаря Ashok R для быстрого кода.

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

Он разбивается в случае представлений с шириной, сравнительно большей, чем высота.

введите описание изображения здесь

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

Я создал расширение для этого -

extension UIView {
    func addshadow(top: Bool,
                   left: Bool,
                   bottom: Bool,
                   right: Bool,
                   shadowRadius: CGFloat = 2.0) {

        self.layer.masksToBounds = false
        self.layer.shadowOffset = CGSize(width: 0.0, height: 0.0)
        self.layer.shadowRadius = shadowRadius
        self.layer.shadowOpacity = 1.0

        let path = UIBezierPath()
        var x: CGFloat = 0
        var y: CGFloat = 0
        var viewWidth = self.frame.width
        var viewHeight = self.frame.height

        // here x, y, viewWidth, and viewHeight can be changed in
        // order to play around with the shadow paths.
        if (!top) {
            y+=(shadowRadius+1)
        }
        if (!bottom) {
            viewHeight-=(shadowRadius+1)
        }
        if (!left) {
            x+=(shadowRadius+1)
        }
        if (!right) {
            viewWidth-=(shadowRadius+1)
        }
        // selecting top most point
        path.move(to: CGPoint(x: x, y: y))
        // Move to the Bottom Left Corner, this will cover left edges
        /*
         |☐
         */
        path.addLine(to: CGPoint(x: x, y: viewHeight))
        // Move to the Bottom Right Corner, this will cover bottom edge
        /*
         ☐
         -
         */
        path.addLine(to: CGPoint(x: viewWidth, y: viewHeight))
        // Move to the Top Right Corner, this will cover right edge
        /*
         ☐|
         */
        path.addLine(to: CGPoint(x: viewWidth, y: y))
        // Move back to the initial point, this will cover the top edge
        /*
         _
         ☐
         */        
        path.close()
        self.layer.shadowPath = path.cgPath
    }

и установите логическое значение true для той стороны, в которой вы хотите, чтобы тень отображалась

myView.addshadow(top: false, left: true, bottom: true, right: true, shadowRadius: 2.0)

//теневой радиус является необязательным выше и устанавливается по умолчанию на 2.0

введите описание изображения здесь

или myView.addshadow(top: true, left: true, bottom: true, right: true, shadowRadius: 2.0) введите описание изображения здесь

или myView.addshadow(top: false, left: false, bottom: true, right: true, shadowRadius: 2.0)

введите описание изображения здесь