it-swarm.com.ru

Нарисуйте тень только с 3 сторон 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 не поможет мне.

Заранее спасибо!

21
Sergey Grischyov

Я знаю, вы говорите, что настройка 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

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

49
Ryan Poolos

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

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

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

 image with triangle shadow

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

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

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

 enter image description here

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

 enter image description here

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

 enter image description here

7
Saurabh Yadav

Обновление Райан Пулос Ответ на Swift 3.0

Благодаря Райан Пулос

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

Результат: 

 image

3
Ashok R

Попробуй это 

extension CALayer {
func applySketchShadow(color: UIColor, alpha: CGFloat, x: CGFloat, y: CGFloat, blur: CGFloat, spread: CGFloat)
{
    shadowColor = color.cgColor
    shadowOpacity = alpha
    shadowOffset = CGSize(width: x, height: y)
    shadowRadius = blur / 2.0
    if spread == 0 {
        shadowPath = nil
    } else {
        let dx = -spread
        let rect = bounds.insetBy(dx: dx, dy: dx)
        shadowPath = UIBezierPath(rect: rect).cgPath
    }
}
0
roopesh chowdary