UIView с закругленными углами и тени?

390

Я хочу пользовательский UIView...: я просто хотел чистый белый вид с закругленными углами и легкой тенью (без эффекта освещения). Я могу сделать каждый из них один за другим, но происходят обычные clipToBounds/ maskToBoundsконфликты.

Адитья Вайдям
источник
1
Поскольку в комментарии ниже вы говорите, что вы работали с использованием CoreGraphics, не могли бы вы поделиться ответом с сообществом, чтобы вы могли помочь другим в такой же ситуации, как они пытались помочь вам?
lnafziger
Извините, это было довольно давно, и у меня больше нет источника. Я переопределил -drawRect: и использовал UIBezierPath, чтобы нарисовать прямоугольник, и применил тень к слою, поддерживающему вид ... если я правильно помню. :)
Адитья Вайдям
5
Принятый ответ не работает!
onmyway133
1
Возможный дубликат Giving UIView закругленные углы
1
@Sachavijay Вы должны проверить даты обоих сообщений, прежде чем комментировать.
Адитья Вайдям

Ответы:

443

Следующий фрагмент кода добавляет границу, радиус границы и тень к v, a UIView:

// border radius
[v.layer setCornerRadius:30.0f];

// border
[v.layer setBorderColor:[UIColor lightGrayColor].CGColor];
[v.layer setBorderWidth:1.5f];

// drop shadow
[v.layer setShadowColor:[UIColor blackColor].CGColor];
[v.layer setShadowOpacity:0.8];
[v.layer setShadowRadius:3.0];
[v.layer setShadowOffset:CGSizeMake(2.0, 2.0)];

Вы можете настроить параметры в соответствии с вашими потребностями.

Кроме того, добавьте платформу QuartzCore в свой проект и:

#import <QuartzCore/QuartzCore.h>

Смотрите мой другой ответ относительно masksToBounds.


Запись

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

Эван Мулавски
источник
83
Проблема в том, что когда я устанавливаю радиус угла, он устанавливает maskToBounds: YES, тогда как тень требует clipToBounds: NO (где clipToBounds делает то же самое, что maskToBounds)
Адитья Вайдям
15
та же проблема здесь. Если у меня есть цвет фона, я хочу, чтобы он был обрезан по закругленным углам. Чтобы сделать это, я должен использовать maskToBounds = TRUE, но затем тень
исчезает
3
Для таких новичков, как я: мне пришлось импортировать инфраструктуру QuartzCore в мой проект, чтобы вызывать методы объекта слоя.
SilithCrowe
38
Чтобы заставить это работать правильно, используйте внутреннее представление контейнера, в котором будут находиться ваша граница и цвет фона, оба с угловым радиусом. Это представление будет ограничено! Во втором, внешнем виде контейнера будет размещен первый, имеющий ту же рамку, только с тенью. Я делал это довольно много раз, чтобы объединить границу, тень и радиус угла. Это действительно раздражает, но работает очень хорошо.
Kpmurphy91
23
Не работает Понятия не имею, почему так много голосов. Было ли это применимо в старых версиях?
Ярнео
629

стриж

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

// corner radius
blueView.layer.cornerRadius = 10

// border
blueView.layer.borderWidth = 1.0
blueView.layer.borderColor = UIColor.black.cgColor

// shadow
blueView.layer.shadowColor = UIColor.black.cgColor
blueView.layer.shadowOffset = CGSize(width: 3, height: 3)
blueView.layer.shadowOpacity = 0.7
blueView.layer.shadowRadius = 4.0

Изучение вариантов

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

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

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

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

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

Проблема 1: Тень отсекается

Что если есть подслои или подпредставления (например, изображение), содержимое которых мы хотим обрезать до границ нашего представления?

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

Мы можем сделать это с

blueView.layer.masksToBounds = true

(Альтернативно, blueView.clipsToBounds = trueдает тот же результат .)

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

Но нет! Тень также была обрезана, потому что она выходит за границы! Что делать? Что делать?

Решение

Используйте отдельные виды для тени и границы. Базовый вид прозрачен и имеет тень. Представление границы обрезает любой другой субконтент, который у него есть, к его границам.

// add the shadow to the base view
baseView.backgroundColor = UIColor.clear
baseView.layer.shadowColor = UIColor.black.cgColor
baseView.layer.shadowOffset = CGSize(width: 3, height: 3)
baseView.layer.shadowOpacity = 0.7
baseView.layer.shadowRadius = 4.0

// add the border to subview
let borderView = UIView()
borderView.frame = baseView.bounds
borderView.layer.cornerRadius = 10
borderView.layer.borderColor = UIColor.black.cgColor
borderView.layer.borderWidth = 1.0
borderView.layer.masksToBounds = true
baseView.addSubview(borderView)

// add any other subcontent that you want clipped
let otherSubContent = UIImageView()
otherSubContent.image = UIImage(named: "lion")
otherSubContent.frame = borderView.bounds
borderView.addSubview(otherSubContent)

Это дает следующий результат:

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

Проблема 2: низкая производительность

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

baseView.layer.shadowPath = UIBezierPath(roundedRect: baseView.bounds, cornerRadius: 10).cgPath
baseView.layer.shouldRasterize = true
baseView.layer.rasterizationScale = UIScreen.main.scale

Смотрите этот пост для более подробной информации. Смотрите здесь и здесь также.

Этот ответ был протестирован с Swift 4 и Xcode 9.

Suragch
источник
1
@ EICaptainv2.0, если вам нужна только граница (и / или угловой радиус), вам не нужен отдельный вид. Отдельный вид для ситуации, когда вам нужны закругленные углы и тени .
Сурагч,
2
Это не работает для меня. Когда я устанавливаю фоновый цвет, чтобы очистить базовый вид, тень больше не появляется. Что я делаю неправильно?
Rutger Huijsmans
3
Не работает, настройка baseView.backgroundColor = UIColor.clearудаляет тень. Только если вы установите цвет фона, вы увидите его.
Александр
2
НЕ РАБОТАЙТЕ ДЛЯ МЕНЯ.
Маркус
4
К сведению, я изначально видел ту же проблему, что и другие комментаторы, когда тень базового вида не отображалась, когда его цвет фона был четким. Проблема заключалась в том, что я выполнял только первую часть кода (материал baseView). Как только я добавил borderView в качестве подпредставления, тень начала отображаться. Кажется, что для отображения тени должна быть хотя бы одна видимая граница (или фон) в ее иерархии представления. Поэтому убедитесь, что у borderView.layer.borderWidth> = 0 непрозрачный borderView.layer.borderColor (или непрозрачный цвет фона)
Майк Восселлер,
79

Один из способов сделать это - поместить вид с закругленными углами в вид с тенью.

UIView* roundedView = [[UIView alloc] initWithFrame: frame];
roundedView.layer.cornerRadius = 5.0;
roundedView.layer.masksToBounds = YES;

UIView* shadowView = [[UIView alloc] initWithFrame: frame];
shadowView.layer.shadowColor = [UIColor blackColor].CGColor;
shadowView.layer.shadowRadius = 5.0;
shadowView.layer.shadowOffset = CGSizeMake(3.0, 3.0);
shadowView.layer.shadowOpacity = 1.0;
[shadowView addSubview: roundedView];

Затем вы можете добавить shadowView куда угодно.

Дэвид С.
источник
5
Amit, вы должны установить maskToBounds / clipToBounds = YES только для * округленного просмотра *. НЕ устанавливайте это в shadowView. Я не пробовал приведенный выше код, но точно знаю, что это решение определенно работает, хотя и не идеально. Более высокий shadowRadius позаботится о областях углового радиуса. Установите shadowRadius на 0 или 1, и вы заметите, что я пытаюсь сказать.
Deepak GM
2
Что-то вроде shadowView.layer.shadowOpacity = 0.6; отсутствует
Бо.
3
"shadowView.layer.opacity = 1.0" должно быть "shadowView.layer.shadowOpacity = 1.0"
Крис
Работает на iOS 9, если использовать shadowView.layer.shadowOpacity = 1.0
Мансуров Руслан
Код исправлен для shadowOpacity
Softlion
63

Посмотрите пример проекта на GitHub, чтобы убедиться, что вы используете компонент правильно.

Решение Simple Swift 5 без каких-либо дополнительных подпредставлений или подклассов:

extension UIView {

    func addShadow(offset: CGSize, color: UIColor, radius: CGFloat, opacity: Float) {
        layer.masksToBounds = false
        layer.shadowOffset = offset
        layer.shadowColor = color.cgColor
        layer.shadowRadius = radius
        layer.shadowOpacity = opacity

        let backgroundCGColor = backgroundColor?.cgColor
        backgroundColor = nil
        layer.backgroundColor =  backgroundCGColor
    }
}

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

После этого просто позвоните вот viewDidLoadтак:

button.addShadow(offset: CGSize.init(width: 0, height: 3), color: UIColor.black, radius: 2.0, opacity: 0.35)

Конечный результат:

результат

Супер просто и просто!

Сергей Грищев
источник
Это работает на кнопках? Потому что это не работает с моей стороны.
Чезаре
Я попытался следовать точным шагам, которые вы предложили. Но все равно не повезло. Было бы здорово, если бы вы поделились примером (на Github), чтобы увидеть, как вы это сделали, что кажется невозможным для меня и других людей.
Hemang
Удалось заставить его работать только удалив эту строку layer.shadowPath = UIBezierPath.init(roundedRect: layer.bounds, cornerRadius: layer.cornerRadius).cgPath. Хотя не могу объяснить, почему у кого-то есть объяснение этому?
Трупин
@Curnelious, не стесняйтесь взглянуть на обновленный ответ с примером проекта Xcode. Это не может не работать :)
Сергей Грищев
3
Это сработало и для меня, нужно еще кое-что сделать, чтобы очистить фоновый цвет всех подпредставлений, чтобы только вид контейнера имел видимый фон, и это решило мою проблему. Спасибо!! @SergeyGrischyov
Rishabh
42

Это сработало для меня. Хитрость заключалась в том, чтобы переместить цвет фона с основного вида на слой.

CALayer *layer = view.layer;
layer.cornerRadius = 15.0f;
layer.masksToBounds = NO;

layer.shadowOffset = CGSizeMake(0, 3);
layer.shadowColor = [[UIColor blackColor] CGColor];
layer.shadowRadius = 2.0f;
layer.shadowOpacity = 0.35f;
layer.shadowPath = [[UIBezierPath bezierPathWithRoundedRect:layer.bounds cornerRadius:layer.cornerRadius] CGPath];

CGColorRef  bColor = view.backgroundColor.CGColor;
view.backgroundColor = nil;
layer.backgroundColor =  bColor ;
Ade
источник
Хотя все другие решения работают, и, возможно, они носят более общий характер, это, безусловно, лучшее решение проблемы. Добавление подпредставлений или подслоев создает мир или боль, пытаясь сохранить размеры кадра, или, в лучшем случае, может вызвать проблемы с производительностью.
emem
Это должно быть ответом. Чистый и элегантный.
Axy
Лучшее решение и определенно элегантный!
Роберто Ферраз
Вау, это на самом деле работает. Я не понимаю, почему это должно работать - вы думаете, что backgroundColor представления будет напрямую отображаться на свойство layer.backgroundColor на iOS - но это РАБОТАЕТ. (Xcode 8, Swift 3.) Отлично, и спасибо. Это должен быть принятый ответ.
Уомбл
Я создал версию вашего ответа для Swift 3.1, используя UIView extensionздесь - stackoverflow.com/a/43295741/1313939 спасибо за вдохновение!
Сергей Грищев
26

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

[UIBezierPath bezierPathWithRoundedRect:cell.bounds cornerRadius:12]

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

//this is the border for the UIView that is added to a cell
cell.backgroundView.layer.cornerRadius = 12;
cell.backgroundView.layer.masksToBounds = YES;
cell.backgroundView.layer.borderColor = [UIColor darkGrayColor].CGColor;
cell.backgroundView.layer.borderWidth = 1;

//this is the shadow around the cell itself (cannot have round corners with borders and shadow, need to use two views
cell.layer.shadowRadius = 2;
cell.layer.cornerRadius = 12;
cell.layer.masksToBounds = NO;
[[cell layer] setShadowColor:[[UIColor darkGrayColor] CGColor]];

[[cell layer] setShadowOffset:CGSizeMake(0.0,0.0)];
[[cell layer] setShadowOpacity:1.0];

UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:cell.bounds cornerRadius:12];
[[cell layer] setShadowPath:[path CGPath]];
Алекс Стоун
источник
Лучший ответ, потому что он объясняет правильный способ добавить тень в округлом виде. Спасибо @Alex Stone
программист
17

Если вы боретесь из - за округляемой cornersпротив subviewsпротив masksToBounds, то попробуйте использовать свою функцию:

- (UIView*)putView:(UIView*)view insideShadowWithColor:(UIColor*)color andRadius:(CGFloat)shadowRadius andOffset:(CGSize)shadowOffset andOpacity:(CGFloat)shadowOpacity
{
    CGRect shadowFrame; // Modify this if needed
    shadowFrame.size.width = 0.f;
    shadowFrame.size.height = 0.f;
    shadowFrame.origin.x = 0.f;
    shadowFrame.origin.y = 0.f;
    UIView * shadow = [[UIView alloc] initWithFrame:shadowFrame];
    shadow.userInteractionEnabled = NO; // Modify this if needed
    shadow.layer.shadowColor = color.CGColor;
    shadow.layer.shadowOffset = shadowOffset;
    shadow.layer.shadowRadius = shadowRadius;
    shadow.layer.masksToBounds = NO;
    shadow.clipsToBounds = NO;
    shadow.layer.shadowOpacity = shadowOpacity;
    [view.superview insertSubview:shadow belowSubview:view];
    [shadow addSubview:view];
    return shadow;
}

назовите это на ваш взгляд. имеет ли ваш вид закругленные углы, независимо от его размера, формы - будет нарисована хорошая тень.

Просто сохраните возвращаемое значение функции, чтобы вы могли обращаться к нему, когда хотите удалить таблицу (или, например, использовать insertSubview:aboveView:)

daniel.gindi
источник
это работает отлично. Но если представление имеет распознаватели жестов, то оно не будет работать. как мы можем решить это?
manujmv
@manujmv Видите ли вы строки, где указано "// Изменить это при необходимости"? Это то, что вам нужно. shadow.userInteractionEnabled = YES;
daniel.gindi
@manujmv, тогда вы должны проверить кадры представления и подпредставления, чтобы понять почему. что-то, вероятно, не тут. этот точный код работает для меня в некоторых очень хороших приложениях
daniel.gindi
2
Это решение прекрасно работает для UITableView с закругленными углами. Хотел бы я больше отдать это голосам. Спасибо!
Крис Харт
@ CarlosEduardoLópez Вы видите shadow.userInteractionEnabled = NO; // Modify this if neededлинию? Так что это тот случай, когда это необходимо. userInteractionEnabledявляется основным и популярным свойством, с которым вы уже должны быть знакомы :-)
daniel.gindi
12

Используя Swift 4 и Xcode 9 , это рабочий пример округления ImageViewс тенью и границей.

    //set dimensions and position of image (in this case, centered)
    let imageHeight: CGFloat = 150, imageWidth: CGFloat = 150
    let xPosition = (self.view.frame.width / 2) - (imageWidth / 2)
    let yPosition = (self.view.frame.height / 2) - (imageHeight / 2)

    //set desired corner radius
    let cornerRadius: CGFloat = 20

    //create container for the image
    let imageContainer = UIView(frame: CGRect(x: xPosition, y: yPosition, width: imageWidth, height: imageHeight))

    //configure the container
    imageContainer.clipsToBounds = false
    imageContainer.layer.shadowColor = UIColor.black.cgColor
    imageContainer.layer.shadowOpacity = 1
    imageContainer.layer.shadowOffset = CGSize(width: 3.0, height: 3.0)
    imageContainer.layer.shadowRadius = 5
    imageContainer.layer.shadowPath = UIBezierPath(roundedRect: imageContainer.bounds, cornerRadius: cornerRadius).cgPath

    //create imageView
    let imageView = UIImageView(frame: imageContainer.bounds)

    //configure the imageView
    imageView.clipsToBounds = true
    imageView.layer.cornerRadius = cornerRadius
    //add a border (if required)
    imageView.layer.borderColor = UIColor.black.cgColor
    imageView.layer.borderWidth = 1.0
    //set the image
    imageView.image = UIImage(named: "bird")

    //add the views to the superview
    view.addSubview(imageContainer)
    imageContainer.addSubview(imageView)

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

Если вы хотите, чтобы изображение было круглым: (и показано без рамки)

let cornerRadius = imageWidth / 2

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

rbaldwin
источник
7

Я создал помощника на UIView

@interface UIView (Helper)

- (void)roundCornerswithRadius:(float)cornerRadius
               andShadowOffset:(float)shadowOffset;
@end

Вы можете назвать это так

[self.view roundCornerswithRadius:5 andShadowOffset:5];

Вот реализация

- (void)roundCornerswithRadius:(float)cornerRadius
               andShadowOffset:(float)shadowOffset
{
    const float CORNER_RADIUS = cornerRadius;
    const float SHADOW_OFFSET = shadowOffset;
    const float SHADOW_OPACITY = 0.5;
    const float SHADOW_RADIUS = 3.0;

    UIView *superView = self.superview;

    CGRect oldBackgroundFrame = self.frame;
    [self removeFromSuperview];

    CGRect frameForShadowView = CGRectMake(0, 0, oldBackgroundFrame.size.width, oldBackgroundFrame.size.height);
    UIView *shadowView = [[UIView alloc] initWithFrame:frameForShadowView];
    [shadowView.layer setShadowOpacity:SHADOW_OPACITY];
    [shadowView.layer setShadowRadius:SHADOW_RADIUS];
    [shadowView.layer setShadowOffset:CGSizeMake(SHADOW_OFFSET, SHADOW_OFFSET)];

    [self.layer setCornerRadius:CORNER_RADIUS];
    [self.layer setMasksToBounds:YES];

    [shadowView addSubview:self];
    [superView addSubview:shadowView];

}
Зайин Криге
источник
2
Это хорошее элегантное решение. Убедитесь, что ваш вид был добавлен в суперпредставление перед использованием. Я добавил некоторые параметры, чтобы дать мне больше контроля над тенью, но в целом работает отлично. Спасибо!
Аарон Вег
Это хорошее решение, но оно не работает с автопоставкой: представление будет отрисовано в начале координат 0,0
gderaco
5

После одного целого дня исследования кругового обзора с тенью я рад опубликовать здесь свой пользовательский класс uiview, надеясь закончить этот вопрос:

RoundCornerShadowView.h

#import <UIKit/UIKit.h>

@interface RoundCornerShadowView : UIView

@end

RoundCornerShadowView.m

#import "RoundCornerShadowView.h"

@implementation RoundCornerShadowView

// *** must override this method, not the other method ***
// otherwise, the background corner doesn't disappear....
// @2015/05/29
-(void) layoutSubviews {
    [super layoutSubviews];//is must to ensure rightly layout children view

    //1. first, create Inner layer with content
    CALayer *innerView = [CALayer layer];
    innerView.frame = CGRectMake(0,0,self.bounds.size.width,self.bounds.size.height);
    //instead of: innerView.frame = self.frame;
    innerView.borderWidth = 1.0f;
    innerView.cornerRadius = 6.0f;
    innerView.masksToBounds = YES;
    innerView.borderColor = [[UIColor lightGrayColor] CGColor];
    innerView.backgroundColor = [[UIColor whiteColor] CGColor];
    //put the layer to the BOTTOM of layers is also a MUST step...
    //otherwise this layer will overlay the sub uiviews in current uiview...
    [self.layer insertSublayer:innerView atIndex:0];

    //2. then, create shadow with self layer
    self.layer.masksToBounds = NO;
    self.layer.shadowColor = [[UIColor darkGrayColor] CGColor];
    self.layer.shadowOpacity = 0.4f;
    //shadow length
    self.layer.shadowRadius = 2.0f;
    //no offset
    self.layer.shadowOffset = CGSizeMake(0, 0);
    //right down shadow
    //[self.layer setShadowOffset: CGSizeMake(1.0f, 1.0f)];

    //3. last but important, MUST clear current view background color, or the color will show in the corner!
    self.backgroundColor = [UIColor clearColor];
}

@end

поэтому, НЕТ необходимости добавлять подпредставление в представлении или ниже в целевом представлении, просто добавьте один слой в текущем представлении и сделайте 3 шага, чтобы завершить его!

внимательно посмотрите на комментарии в коде, это полезно для понимания компонента!

lwz7512
источник
5

Что-то быстрое испытано в Swift 4

import UIKit

extension UIView {
    @IBInspectable var dropShadow: Bool {
        set{
            if newValue {
                layer.shadowColor = UIColor.black.cgColor
                layer.shadowOpacity = 0.4
                layer.shadowRadius = 1
                layer.shadowOffset = CGSize.zero
            } else {
                layer.shadowColor = UIColor.clear.cgColor
                layer.shadowOpacity = 0
                layer.shadowRadius = 0
                layer.shadowOffset = CGSize.zero
            }
        }
        get {
            return layer.shadowOpacity > 0
        }
    }
}

Производит

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

Если вы включите его в Инспекторе, как это:

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

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

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

(Я добавил ранее cornerRadius = 8)

:)

dGambit
источник
5

Вы должны использовать shadowViewи использоватьroundView

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

shadowView

  • Должен иметь цвет фона
  • Должен лежать позади roundView
  • Хитрость в том, чтобы расположить shadowViewнемного внутри, и его тень должна светиться. Отрегулируйте insetsтак, чтобы shadowViewсзади было полностью не видноroundView

Roundview

  • Должны клипы подпредставления

Код

addSubviews(shadowView, roundView)
roundView.addSubviews(titleLabel, subtitleLabel, imageView)

// need inset
shadowView.pinEdges(view: self, inset: UIEdgeInsets(constraintInsets: 2))
roundView.pinEdges(view: self)

do {
  shadowView.backgroundColor = .white // need background
  let layer = shadowView.layer
  layer.shadowColor = UIColor.black.cgColor
  layer.shadowRadius = 3
  layer.shadowOffset = CGSize(width: 3, height: 3)
  layer.shadowOpacity = 0.7
  layer.shouldRasterize = true
}

do {
  roundView.backgroundColor = .white
  let layer = roundView.layer
  layer.masksToBounds = true
  layer.cornerRadius = 5
}

Или вы можете просто сделать ниже без указания clipToBounds/maskToBounds

layer.shadowColor = UIColor.gray.cgColor
layer.shadowOffset = CGSize(width: 3, height: 3)
layer.shadowOpacity = 0.8
onmyway133
источник
4

Swift 3 & IBInspectable решение:
вдохновлено решением Ade

Сначала создайте расширение UIView:

//
//  UIView-Extension.swift
//  

import Foundation
import UIKit

@IBDesignable
extension UIView {
     // Shadow
     @IBInspectable var shadow: Bool {
          get {
               return layer.shadowOpacity > 0.0
          }
          set {
               if newValue == true {
                    self.addShadow()
               }
          }
     }

     fileprivate func addShadow(shadowColor: CGColor = UIColor.black.cgColor, shadowOffset: CGSize = CGSize(width: 3.0, height: 3.0), shadowOpacity: Float = 0.35, shadowRadius: CGFloat = 5.0) {
          let layer = self.layer
          layer.masksToBounds = false

          layer.shadowColor = shadowColor
          layer.shadowOffset = shadowOffset
          layer.shadowRadius = shadowRadius
          layer.shadowOpacity = shadowOpacity
          layer.shadowPath = UIBezierPath(roundedRect: layer.bounds, cornerRadius: layer.cornerRadius).cgPath

          let backgroundColor = self.backgroundColor?.cgColor
          self.backgroundColor = nil
          layer.backgroundColor =  backgroundColor
     }


     // Corner radius
     @IBInspectable var circle: Bool {
          get {
               return layer.cornerRadius == self.bounds.width*0.5
          }
          set {
               if newValue == true {
                    self.cornerRadius = self.bounds.width*0.5
               }
          }
     }

     @IBInspectable var cornerRadius: CGFloat {
          get {
               return self.layer.cornerRadius
          }

          set {
               self.layer.cornerRadius = newValue
          }
     }


     // Borders
     // Border width
     @IBInspectable
     public var borderWidth: CGFloat {
          set {
               layer.borderWidth = newValue
          }

          get {
               return layer.borderWidth
          }
     }

     // Border color
     @IBInspectable
     public var borderColor: UIColor? {
          set {
               layer.borderColor = newValue?.cgColor
          }

          get {
               if let borderColor = layer.borderColor {
                    return UIColor(cgColor: borderColor)
               }
               return nil
          }
     }
}

Затем просто выберите свой UIView в настройке интерфейса, установив тень и радиус угла , как показано ниже:

Выбор вашего UIView

Установка тени и угловой радиус

Результат!

Результат

Томас Калмон
источник
Как и любое другое «решение» в этой теме, оно просто не работает, по крайней мере, на iOS 11.0 / Swift 4.1.
недобросовестный
Вы читали "Swift 3" в начале темы? Таким образом, это означает, что это решение Swift 3, я не тестировал его в Swift 4.1, потому что он мне больше не нужен. Не стесняйтесь редактировать ответ и дать решение. ;) Приветствия
Томас Калмон
3

Вот решение проблемы конфликта с masksToBounds, оно работает для меня.

После установки corderRadius / borderColor / shadow и т. Д. Установите для masksToBounds значение NO:

v.layer.masksToBounds = NO;
Шаопенг Ван
источник
Это сработало для меня! о боже мой, я почти все трюки выше вы ответили! спасибо Shaopeng.
MontDeska
3

Тень + Граница + Угловой Радиус введите описание изображения здесь

    scrollview.backgroundColor = [UIColor whiteColor]; 
    CALayer *ScrlViewLayer = [scrollview layer];
    [ScrlViewLayer setMasksToBounds:NO ];
    [ScrlViewLayer setShadowColor:[[UIColor lightGrayColor] CGColor]];
    [ScrlViewLayer setShadowOpacity:1.0 ];
    [ScrlViewLayer setShadowRadius:6.0 ];
    [ScrlViewLayer setShadowOffset:CGSizeMake( 0 , 0 )];
    [ScrlViewLayer setShouldRasterize:YES];
    [ScrlViewLayer setCornerRadius:5.0];
    [ScrlViewLayer setBorderColor:[UIColor lightGrayColor].CGColor];
    [ScrlViewLayer setBorderWidth:1.0];
    [ScrlViewLayer setShadowPath:[UIBezierPath bezierPathWithRect:scrollview.bounds].CGPath];
Даршит Шах
источник
3

Вот моя версия в Swift 3 для UIView

let corners:UIRectCorner = [.bottomLeft, .topRight]
let path = UIBezierPath(roundedRect: rect, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
let mask = CAShapeLayer()

mask.path = path.cgPath
mask.fillColor = UIColor.white.cgColor

let shadowLayer = CAShapeLayer()
shadowLayer.shadowColor = UIColor.black.cgColor
shadowLayer.shadowOffset = CGSize(width: 0.0, height: 4.0)
shadowLayer.shadowRadius = 6.0
shadowLayer.shadowOpacity = 0.25
shadowLayer.shadowPath = mask.path

self.layer.insertSublayer(shadowLayer, at: 0)
self.layer.insertSublayer(mask, at: 1)
Юнг Дай
источник
3

Swift 4: создание подкласса UIView

class ShadowView: UIView {

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)

        // corner radius
        self.layer.cornerRadius = 10

        // border
        self.layer.borderWidth = 1.0
        self.layer.borderColor = UIColor.black.cgColor

        // shadow
        self.layer.shadowColor = UIColor.black.cgColor
        self.layer.shadowOffset = CGSize(width: 3, height: 3)
        self.layer.shadowOpacity = 0.7
        self.layer.shadowRadius = 4.0
    }

}

С помощью..

Использовать класс теневого вида

benmore99
источник
2

Хорошо, если вы не хотите менять свои кончики и просматривать иерархию, как предложено Дэвидом С., этот метод сделает это за вас. Чтобы добавить закругленные углы и тень к вашему UIImageView, просто используйте этот метод, например:

[Utils roundCornersForImageView:myImageView withCornerRadius:6.0 
andShadowOffset:2.0];

(!) По соображениям производительности я не думаю, что было бы хорошей идеей использовать этот код в чем-то вроде UITableView, так как этот код меняет иерархию представления. Поэтому я предлагаю изменить ваше перо и добавить контейнерное представление для эффекта тени и использовать код Davic C.

+ (void)roundCornersForImageView:(UIImageView *)imageView 
withCornerRadius:(float)cornerRadius andShadowOffset:(float)shadowOffset
{
    const float CORNER_RADIUS = cornerRadius;
    const float BORDER_WIDTH = 1.0; 
    const float SHADOW_OFFSET = shadowOffset;
    const float SHADOW_OPACITY = 0.8;
    const float SHADOW_RADIUS = 3.0;

    //Our old image now is just background image view with shadow
    UIImageView *backgroundImageView = imageView;
    UIView *superView = backgroundImageView.superview;

    //Make wider actual visible rect taking into account shadow
    //offset
    CGRect oldBackgroundFrame = backgroundImageView.frame;
    CGRect newBackgroundFrame = CGRectMake(oldBackgroundFrame.origin.x, oldBackgroundFrame.origin.y, oldBackgroundFrame.size.width + SHADOW_OFFSET, oldBackgroundFrame.size.height + SHADOW_OFFSET);
    [backgroundImageView removeFromSuperview];
    backgroundImageView.frame = newBackgroundFrame;        

    //Make new UIImageView with rounded corners and put our old image
    CGRect frameForRoundedImageView = CGRectMake(0, 0, oldBackgroundFrame.size.width, oldBackgroundFrame.size.height);
    UIImageView *roundedImageView = [[UIImageView alloc]initWithFrame:frameForRoundedImageView];
    roundedImageView.image = imageView.image;
    [roundedImageView.layer setCornerRadius:CORNER_RADIUS];
    [roundedImageView.layer setBorderColor:[UIColor lightGrayColor].CGColor];        
    [roundedImageView.layer setBorderWidth:BORDER_WIDTH]; 
    [roundedImageView.layer setMasksToBounds:YES];

    //Set shadow preferences
    [backgroundImageView setImage:nil];
    [backgroundImageView.layer setShadowColor:[UIColor blackColor].CGColor];
    [backgroundImageView.layer setShadowOpacity:SHADOW_OPACITY];
    [backgroundImageView.layer setShadowRadius:SHADOW_RADIUS];
    [backgroundImageView.layer setShadowOffset:CGSizeMake(SHADOW_OFFSET, SHADOW_OFFSET)];   

    //Add out two image views back to the view hierarchy.
    [backgroundImageView addSubview:roundedImageView];
    [superView addSubview:backgroundImageView];   
}    
Роман Миненок
источник
2

Старый поток все еще актуален ...

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

+ (UIView*)putView:(UIView*)view insideShadowWithColor:(CGColorRef)color 
                                 andRadius:(CGFloat)shadowRadius 
                                 andOffset:(CGSize)shadowOffset 
                                 andOpacity:(CGFloat)shadowOpacity
{
    // Must have same position like "view"
    UIView *shadow = [[UIView alloc] initWithFrame:view.frame]; 

    shadow.layer.contentsScale = [UIScreen mainScreen].scale;
    shadow.userInteractionEnabled = YES; // Modify this if needed
    shadow.layer.shadowColor = color;
    shadow.layer.shadowOffset = shadowOffset;
    shadow.layer.shadowRadius = shadowRadius;
    shadow.layer.masksToBounds = NO;
    shadow.clipsToBounds = NO;
    shadow.layer.shadowOpacity = shadowOpacity;
    shadow.layer.rasterizationScale = [UIScreen mainScreen].scale;
    shadow.layer.shouldRasterize = YES;

    [view.superview insertSubview:shadow belowSubview:view];
    [shadow addSubview:view];

    // Move view to the top left corner inside the shadowview 
    // ---> Buttons etc are working again :)
    view.frame = CGRectMake(0, 0, view.frame.size.width, view.frame.size.height);

    return shadow;
}
NickBln
источник
2

Следующее работает лучше всего для меня (этот код находится в расширении UIView, поэтому self обозначает некоторый UIView, к которому мы должны добавить тень и закругленный угол)

- (void)addShadowViewWithCornerRadius:(CGFloat)radius {

UIView *container = self.superview;

if (!container) {
    return;
}

UIView *shadowView = [[UIView alloc] init];
shadowView.translatesAutoresizingMaskIntoConstraints = NO;
shadowView.backgroundColor = [UIColor lightGrayColor];
shadowView.layer.cornerRadius = radius;
shadowView.layer.masksToBounds = YES;

[container addSubview:shadowView];
[container bringSubviewToFront:shadowView];

[container addConstraint:[NSLayoutConstraint constraintWithItem:shadowView
                                                      attribute:NSLayoutAttributeWidth
                                                      relatedBy:NSLayoutRelationEqual
                                                         toItem:self
                                                      attribute:NSLayoutAttributeWidth
                                                     multiplier:1.0
                                                       constant:0.0]];
[container addConstraint:[NSLayoutConstraint constraintWithItem:shadowView
                                                      attribute:NSLayoutAttributeLeading
                                                      relatedBy:NSLayoutRelationEqual
                                                         toItem:self
                                                      attribute:NSLayoutAttributeLeading
                                                     multiplier:1.0
                                                       constant:2.0]];

[container addConstraint:[NSLayoutConstraint constraintWithItem:shadowView
                                                      attribute:NSLayoutAttributeHeight
                                                      relatedBy:NSLayoutRelationEqual
                                                         toItem:self
                                                      attribute:NSLayoutAttributeHeight
                                                     multiplier:1.0
                                                       constant:0.0]];
[container addConstraint:[NSLayoutConstraint constraintWithItem:shadowView
                                                      attribute:NSLayoutAttributeTop
                                                      relatedBy:NSLayoutRelationEqual
                                                         toItem:self
                                                      attribute:NSLayoutAttributeTop
                                                     multiplier:1.0
                                                       constant:2.0]];
[container sendSubviewToBack:shadowView];
}

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

Мехул Пармар
источник
1

Ответ от daniel.gindi выше помог мне! (+1 Даниэль) Однако мне пришлось внести незначительные корректировки - изменить размер shadowFrame, чтобы он соответствовал размеру кадра представления, и включить взаимодействие с пользователем. Вот обновленный код:

+ (UIView*)putView:(UIView*)view insideShadowWithColor:(UIColor*)color andRadius:(CGFloat)shadowRadius andOffset:(CGSize)shadowOffset andOpacity:(CGFloat)shadowOpacity
{
    CGRect shadowFrame; // Modify this if needed

    // Modified this line
    shadowFrame.size = CGSizeMake(view.frame.size.width, view.frame.size.height);

    shadowFrame.origin.x = 0.f;
    shadowFrame.origin.y = 0.f;
    UIView * shadow = [[UIView alloc] initWithFrame:shadowFrame];

    // Modified this line
    shadow.userInteractionEnabled = YES;
    shadow.layer.shadowColor = color.CGColor;
    shadow.layer.shadowOffset = shadowOffset;
    shadow.layer.shadowRadius = shadowRadius;
    shadow.layer.masksToBounds = NO;
    shadow.clipsToBounds = NO;
    shadow.layer.shadowOpacity = shadowOpacity;

    [shadow addSubview:view];
    return shadow;
}

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

UIView *shadow = [self putView:vc.view 
         insideShadowWithColor:[UIColor blackColor]
                     andRadius:5.0 
                     andOffset:CGSizeMake(0.0, 0.0) 
                    andOpacity:1.0];
vc.view = shadow;
vc.view.layer.cornerRadius = 5.0;
vc.view.layer.masksToBounds = YES;
Digitrance
источник
1

Я делаю некоторые изменения в коде daniel.gindi

Это все, что вам нужно, чтобы это работало.

+ (void)putView:(UIView*)view insideShadowWithColor:(UIColor*)color andBlur:         (CGFloat)blur andOffset:(CGSize)shadowOffset andOpacity:(CGFloat)shadowOpacity
{
    CGRect shadowFrame = view.frame;
    UIView * shadow = [[UIView alloc] initWithFrame:shadowFrame];
    shadow.backgroundColor = [UIColor redColor];
    shadow.userInteractionEnabled = YES; // Modify this if needed
    shadow.layer.shadowColor = color.CGColor;
    shadow.layer.shadowOffset = shadowOffset;
    shadow.layer.shadowRadius = blur;
    shadow.layer.cornerRadius = view.layer.cornerRadius;
    shadow.layer.masksToBounds = NO;
    shadow.clipsToBounds = NO;
    shadow.layer.shadowOpacity = shadowOpacity;
    [view.superview insertSubview:shadow belowSubview:view];
}
Карлос Лопес
источник
1

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

Вот фрагмент кода Class Methodс помощью protocol:

@implementation UIMethods

+ (UIView *)genComposeButton:(UIViewController <UIComposeButtonDelegate> *)observer;
{
    UIView *shadow = [[UIView alloc]init];
    shadow.layer.cornerRadius = 5.0;
    shadow.layer.shadowColor = [[UIColor blackColor] CGColor];
    shadow.layer.shadowOpacity = 1.0;
    shadow.layer.shadowRadius = 10.0;
    shadow.layer.shadowOffset = CGSizeMake(0.0f, -0.5f);

    UIButton *btnCompose = [[UIButton alloc]initWithFrame:CGRectMake(0, 0,60, 60)];
    [btnCompose setUserInteractionEnabled:YES];
    btnCompose.layer.cornerRadius = 30;
    btnCompose.layer.masksToBounds = YES;
    [btnCompose setImage:[UIImage imageNamed:@"60x60"] forState:UIControlStateNormal];
    [btnCompose addTarget:observer action:@selector(btnCompose_click:) forControlEvents:UIControlEventTouchUpInside];
    [shadow addSubview:btnCompose];
    return shadow;
}

В приведенном выше коде btnCompose_click:станет @requiredделегат метод, который будет срабатывать при нажатии кнопки.

И вот я добавил кнопку к моему UIViewControllerтак:

UIView *btnCompose = [UIMethods genComposeButton:self];
btnCompose.frame = CGRectMake(self.view.frame.size.width - 75,
                          self.view.frame.size.height - 75,
                          60, 60);
[self.view addSubview:btnCompose];

Результат будет выглядеть так:

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

Вайбхав Саран
источник
1

Я попробовал так много решений из этого поста и в итоге нашел решение ниже. Это полное доказательство решения, если вам не нужно отбрасывать тени на четкое цветное представление .

- (void)addShadowWithRadius:(CGFloat)shadowRadius withOpacity:(CGFloat)shadowOpacity withOffset:(CGSize)shadowOffset withColor:(UIColor *)shadowColor withCornerradius:(CGFloat)cornerRadius
{
    UIView *viewShadow = [[UIView alloc]initWithFrame:self.frame];
    viewShadow.backgroundColor = [UIColor whiteColor];
    viewShadow.layer.shadowColor = shadowColor.CGColor;
    viewShadow.layer.shadowOffset = shadowOffset;
    viewShadow.layer.shadowRadius = shadowRadius;
    viewShadow.layer.shadowOpacity = shadowOpacity;
    viewShadow.layer.cornerRadius = cornerRadius;
    viewShadow.layer.masksToBounds = NO;
    [self.superview insertSubview:viewShadow belowSubview:self];

    [viewShadow setTranslatesAutoresizingMaskIntoConstraints:NO];
    [self.superview addConstraint:[NSLayoutConstraint constraintWithItem:viewShadow attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeWidth multiplier:1.0 constant:0]];
    [self.superview addConstraint:[NSLayoutConstraint constraintWithItem:viewShadow attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeHeight multiplier:1.0 constant:0]];
    [self.superview addConstraint:[NSLayoutConstraint constraintWithItem:viewShadow attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:viewShadow attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0]];
    [self.superview addConstraint:[NSLayoutConstraint constraintWithItem:viewShadow attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:viewShadow attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0]];
    [self layoutIfNeeded];

    self.layer.cornerRadius = cornerRadius;
    self.layer.masksToBounds = YES;
}
Махеш Агравал
источник
Выражение "дурак". :)
Бен Томас
Я просто поправлял английский. :) Решение работает.
Бен Томас
1

Вот решение, которое будет работать точно!

Я создал расширение UIView с необходимыми краями, чтобы применить тень, как показано ниже


enum AIEdge:Int {
    case
    Top,
    Left,
    Bottom,
    Right,
    Top_Left,
    Top_Right,
    Bottom_Left,
    Bottom_Right,
    All,
    None
}

extension UIView {

    func applyShadowWithCornerRadius(color:UIColor, opacity:Float, radius: CGFloat, edge:AIEdge, shadowSpace:CGFloat)    {

        var sizeOffset:CGSize = CGSize.zero

        switch edge {
        case .Top:
            sizeOffset = CGSize(width: 0, height: -shadowSpace)
        case .Left:
            sizeOffset = CGSize(width: -shadowSpace, height: 0)
        case .Bottom:
            sizeOffset = CGSize(width: 0, height: shadowSpace)
        case .Right:
            sizeOffset = CGSize(width: shadowSpace, height: 0)


        case .Top_Left:
            sizeOffset = CGSize(width: -shadowSpace, height: -shadowSpace)
        case .Top_Right:
            sizeOffset = CGSize(width: shadowSpace, height: -shadowSpace)
        case .Bottom_Left:
            sizeOffset = CGSize(width: -shadowSpace, height: shadowSpace)
        case .Bottom_Right:
            sizeOffset = CGSize(width: shadowSpace, height: shadowSpace)


        case .All:
            sizeOffset = CGSize(width: 0, height: 0)
        case .None:
            sizeOffset = CGSize.zero
        }

        self.layer.cornerRadius = self.frame.size.height / 2
        self.layer.masksToBounds = true;

        self.layer.shadowColor = color.cgColor
        self.layer.shadowOpacity = opacity
        self.layer.shadowOffset = sizeOffset
        self.layer.shadowRadius = radius
        self.layer.masksToBounds = false

        self.layer.shadowPath = UIBezierPath(roundedRect:self.bounds, cornerRadius:self.layer.cornerRadius).cgPath
    }
}

Наконец, вы можете вызвать теневую функцию, как показано ниже для любого вашего подкласса UIView, вы также можете указать ребро, к которому будет применяться тень, попробуйте различные варианты в соответствии с вашими потребностями, изменяя параметры вызова метода ниже.

viewRoundedToBeShadowedAsWell.applyShadowWithCornerRadius(color: .gray, opacity: 1, radius: 15, edge: AIEdge.All, shadowSpace: 15)

Изображение результата

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

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

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

Давал Х. Нена
источник
0

Ответ, предоставленный Эваном Мулавски, будет работать отлично. Уловка в том, что вы должны установить цвет фона для представления clearColor, а свойство masksToBounds - NO.

Вы можете установить любой цвет, который вы хотите для вида, установить его как

v.layer.backgroundColor = your color;

Надеюсь это поможет..

Абдур Рахман
источник
0

Это то, как вы это делаете, с закругленными углами и закругленными тенями, не мешая дорожкам.

//Inner view with content
[imageView.layer setBorderColor:[[UIColor lightGrayColor] CGColor]];
[imageView.layer setBorderWidth:1.0f];
[imageView.layer setCornerRadius:8.0f];
[imageView.layer setMasksToBounds:YES];

//Outer view with shadow
UIView* shadowContainer = [[UIView alloc] initWithFrame:imageView.frame];
[shadowContainer.layer setMasksToBounds:NO];
[shadowContainer.layer setShadowColor:[[UIColor blackColor] CGColor]];
[shadowContainer.layer setShadowOpacity:0.6f];
[shadowContainer.layer setShadowRadius:2.0f];
[shadowContainer.layer setShadowOffset: CGSizeMake(0.0f, 2.0f)];

[shadowContainer addSubview:imageView];

Представление с содержимым, в моем случае UIImageView, имеет угловой радиус и поэтому должно маскироваться до границ.

Мы создаем другое представление одинакового размера для теней, устанавливаем для его maskToBounds значение NO, а затем добавляем представление содержимого в представление контейнера (например, shadowContainer).

Форд Дэвис
источник
0

Я пишу этот метод категории UIView, чтобы решить эту проблему, использует отдельные виды для тени и радиуса угла.

-(UIView *)shadowedWrapViewWithBounds:(CGRect)bounds {
UIView *baseView = [[UIView alloc] init];
baseView.bounds = bounds;
baseView.backgroundColor = [UIColor clearColor];
baseView.layer.shadowColor = [UIColor blackColor].CGColor;
baseView.layer.shadowOffset = CGSizeMake(0, 0);
baseView.layer.shadowOpacity = 0.7;
baseView.layer.shadowRadius = 4.0;

// improve performance
baseView.layer.shadowPath = [UIBezierPath bezierPathWithRoundedRect:baseView.bounds cornerRadius:4].CGPath;
baseView.layer.shouldRasterize = YES;
baseView.layer.rasterizationScale = [UIScreen mainScreen].scale;

[baseView addSubview:self];
//use Masonry autolayout, self can set corner radius
[self makeConstraints:^(MASConstraintMaker *make) {
    make.edges.equalTo(baseView);
}];

return baseView;
}
Лю Чао
источник
0

Swift 4 Решения для создания UICollectionViewCell раунда и добавления теней , без каких - либо расширений и осложнений :)

Примечание. Для простых видов, например кнопок. Смотрите ответ @ suragch в этом посте. https://stackoverflow.com/a/34984063/7698092 . Успешно протестировано для кнопок

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

Эта техника работала для меня без каких-либо расширений и всех сложных вещей. Я работаю с storyBoard.

Техника

Вы должны добавить UIView (скажем, «containerView») внутри вашего UICollectionViewCell в storyBoard и добавить все необходимые представления (кнопки, изображения и т. Д.) Внутри этого containerView. Смотрите скриншот. Структура ячейки

Подключите розетку для контейнера. Добавьте следующие строки кода в делегатскую функцию CellforItemAtIndexPath.

//adds shadow to the layer of cell

cell.layer.cornerRadius = 3.0
    cell.layer.masksToBounds = false
    cell.layer.shadowColor = UIColor.black.cgColor
    cell.layer.shadowOffset = CGSize(width: 0, height: 0)
    cell.layer.shadowOpacity = 0.6

//makes the cell round 

let containerView = cell.containerView!
    containerView.layer.cornerRadius = 8
    containerView.clipsToBounds = true

Вывод

Посмотреть скриншот симулятора Закругленные углы с тенями (UICollectionViewCell)

Авайс Файяз
источник
0
extension UIView {
    func dropRoundedShadowForAllSides() {
        let backgroundView = UIView(frame:self.frame)
        let radius = frame.height/2
        backgroundView.layer.masksToBounds = false
        self.layer.masksToBounds = true
        backgroundView.layer.shadowOffset = CGSize(width: 0.0, height: 0.0)
        backgroundView.layer.shadowRadius = 4
        backgroundView.layer.shadowOpacity = 0.4

        let path = UIBezierPath()

        // Start at the Top Left Corner + radius distance
        path.move(to: CGPoint(x: 2*radius, y: 0.0))

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

        // Move to top right corner + radius down as curve
        let centerPoint1 = CGPoint(x:backgroundView.frame.size.width - radius,y:radius)
        path.addArc(withCenter: centerPoint1, radius: radius, startAngle: 3*(.pi/2), endAngle: 0, clockwise: true)

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

        // Move to top right corner + radius left as curve
        let centerPoint2 = CGPoint(x:backgroundView.frame.size.width - radius,y:backgroundView.frame.size.height - radius)
        path.addArc(withCenter: centerPoint2, radius: radius, startAngle: 0, endAngle: .pi/2, clockwise: true)

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

        // Move to left right corner - radius up as curve
        let centerPoint3 = CGPoint(x:radius,y:backgroundView.frame.size.height - radius)
        path.addArc(withCenter: centerPoint3, radius: radius, startAngle: .pi/2, endAngle: .pi, clockwise: true)

        // Move to the top Left Corner - radius
        path.addLine(to: CGPoint(x: 0, y: radius))

        // Move to top right corner + radius down as curve
        let centerPoint4 = CGPoint(x:radius,y:radius)
        path.addArc(withCenter: centerPoint4, radius: radius, startAngle: .pi, endAngle: 3 * (.pi/2), clockwise: true)

        path.close()

        backgroundView.layer.shadowPath = path.cgPath
        if let superView = self.superview {
            superView.addSubview(backgroundView)
            superView.sendSubview(toBack: backgroundView)
            superView.bringSubview(toFront: self)
        }

    }
}
Дживан Ишвар
источник
Привет, спасибо за ваш ответ, вы должны добавить несколько комментариев к вашему коду, чтобы немного объяснить, как описано в разделе Как ответить .
Креститель Милле-Матиас