J'ai le CALayer suivant:
CAGradientLayer *gradient = [CAGradientLayer layer];
gradient.frame = CGRectMake(8, 57, 296, 30);
gradient.cornerRadius = 3.0f;
gradient.colors = [NSArray arrayWithObjects:(id)[RGB(130, 0, 140) CGColor], (id)[RGB(108, 0, 120) CGColor], nil];
[self.layer insertSublayer:gradient atIndex:0];
Je voudrais ajouter un ombre intérieure effet, mais je ne sais pas trop comment faire cela. Je suppose que je serais obligé de dessiner dans drawRect, mais cela ajouterait le calque au-dessus d'autres objets UIView, car il est censé être une barre derrière certains boutons. Je ne sais donc pas quoi faire?
Je pourrais ajouter un autre calque, mais encore une fois, je ne sais pas comment obtenir l'effet d'ombre interne (comme ceci:
Aide appréciée ...
Pour tous ceux qui se demandent comment dessiner une ombre interne en utilisant Core Graphics selon la suggestion de Costique, voici comment: (sur iOS, ajustez si nécessaire)
Dans votre drawRect: méthode ...
CGRect bounds = [self bounds];
CGContextRef context = UIGraphicsGetCurrentContext();
CGFloat radius = 0.5f * CGRectGetHeight(bounds);
// Create the "visible" path, which will be the shape that gets the inner shadow
// In this case it's just a rounded rect, but could be as complex as your want
CGMutablePathRef visiblePath = CGPathCreateMutable();
CGRect innerRect = CGRectInset(bounds, radius, radius);
CGPathMoveToPoint(visiblePath, NULL, innerRect.Origin.x, bounds.Origin.y);
CGPathAddLineToPoint(visiblePath, NULL, innerRect.Origin.x + innerRect.size.width, bounds.Origin.y);
CGPathAddArcToPoint(visiblePath, NULL, bounds.Origin.x + bounds.size.width, bounds.Origin.y, bounds.Origin.x + bounds.size.width, innerRect.Origin.y, radius);
CGPathAddLineToPoint(visiblePath, NULL, bounds.Origin.x + bounds.size.width, innerRect.Origin.y + innerRect.size.height);
CGPathAddArcToPoint(visiblePath, NULL, bounds.Origin.x + bounds.size.width, bounds.Origin.y + bounds.size.height, innerRect.Origin.x + innerRect.size.width, bounds.Origin.y + bounds.size.height, radius);
CGPathAddLineToPoint(visiblePath, NULL, innerRect.Origin.x, bounds.Origin.y + bounds.size.height);
CGPathAddArcToPoint(visiblePath, NULL, bounds.Origin.x, bounds.Origin.y + bounds.size.height, bounds.Origin.x, innerRect.Origin.y + innerRect.size.height, radius);
CGPathAddLineToPoint(visiblePath, NULL, bounds.Origin.x, innerRect.Origin.y);
CGPathAddArcToPoint(visiblePath, NULL, bounds.Origin.x, bounds.Origin.y, innerRect.Origin.x, bounds.Origin.y, radius);
CGPathCloseSubpath(visiblePath);
// Fill this path
UIColor *aColor = [UIColor redColor];
[aColor setFill];
CGContextAddPath(context, visiblePath);
CGContextFillPath(context);
// Now create a larger rectangle, which we're going to subtract the visible path from
// and apply a shadow
CGMutablePathRef path = CGPathCreateMutable();
//(when drawing the shadow for a path whichs bounding box is not known pass "CGPathGetPathBoundingBox(visiblePath)" instead of "bounds" in the following line:)
//-42 cuould just be any offset > 0
CGPathAddRect(path, NULL, CGRectInset(bounds, -42, -42));
// Add the visible path (so that it gets subtracted for the shadow)
CGPathAddPath(path, NULL, visiblePath);
CGPathCloseSubpath(path);
// Add the visible paths as the clipping path to the context
CGContextAddPath(context, visiblePath);
CGContextClip(context);
// Now setup the shadow properties on the context
aColor = [UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:0.5f];
CGContextSaveGState(context);
CGContextSetShadowWithColor(context, CGSizeMake(0.0f, 1.0f), 3.0f, [aColor CGColor]);
// Now fill the rectangle, so the shadow gets drawn
[aColor setFill];
CGContextSaveGState(context);
CGContextAddPath(context, path);
CGContextEOFillPath(context);
// Release the paths
CGPathRelease(path);
CGPathRelease(visiblePath);
Donc, essentiellement, il y a les étapes suivantes:
Je sais que je suis en retard pour cette fête, mais cela m'aurait aidé à trouver tôt dans mes voyages ...
Reconnaître le crédit dû, c’est essentiellement une modification de l’élaboration de Daniel Thorpe sur la solution de Costique consistant à soustraire une région plus petite d’une région plus grande. Cette version est pour ceux qui utilisent la composition de calque au lieu de remplacer -drawRect:
La classe CAShapeLayer
peut être utilisée pour obtenir le même effet:
CAShapeLayer* shadowLayer = [CAShapeLayer layer];
[shadowLayer setFrame:[self bounds]];
// Standard shadow stuff
[shadowLayer setShadowColor:[[UIColor colorWithWhite:0 alpha:1] CGColor]];
[shadowLayer setShadowOffset:CGSizeMake(0.0f, 0.0f)];
[shadowLayer setShadowOpacity:1.0f];
[shadowLayer setShadowRadius:5];
// Causes the inner region in this example to NOT be filled.
[shadowLayer setFillRule:kCAFillRuleEvenOdd];
// Create the larger rectangle path.
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddRect(path, NULL, CGRectInset(bounds, -42, -42));
// Add the inner path so it's subtracted from the outer path.
// someInnerPath could be a simple bounds rect, or maybe
// a rounded one for some extra fanciness.
CGPathAddPath(path, NULL, someInnerPath);
CGPathCloseSubpath(path);
[shadowLayer setPath:path];
CGPathRelease(path);
[[self layer] addSublayer:shadowLayer];
À ce stade, si votre calque parent ne masque pas ses limites, vous verrez la zone supplémentaire du calque de masque autour des bords du calque. Ce sera 42 pixels de noir si vous venez de copier l'exemple directement. Pour vous en débarrasser, vous pouvez simplement utiliser une autre CAShapeLayer
avec le même chemin et la définir comme masque du calque d'ombre:
CAShapeLayer* maskLayer = [CAShapeLayer layer];
[maskLayer setPath:someInnerPath];
[shadowLayer setMask:maskLayer];
Je n'ai pas mesuré cela moi-même, mais je soupçonne que cette approche associée à la pixellisation est plus performante que le remplacement de -drawRect:
.
Il est possible de dessiner une ombre interne avec Core Graphics en créant un grand tracé rectangle en dehors des limites, en soustrayant un tracé rectangle de la taille d'une limite et en remplissant le tracé obtenu avec une ombre "normale".
Cependant, comme vous devez le combiner avec un calque en dégradé, je pense qu'une solution plus simple consiste à créer une image PNG transparente en 9 parties de l'ombre intérieure et à l'étirer à la bonne taille. L'image de l'ombre en 9 parties ressemblerait à ceci (sa taille est de 21x21 pixels):
CALayer *innerShadowLayer = [CALayer layer];
innerShadowLayer.contents = (id)[UIImage imageNamed: @"innershadow.png"].CGImage;
innerShadowLayer.contentsCenter = CGRectMake(10.0f/21.0f, 10.0f/21.0f, 1.0f/21.0f, 1.0f/21.0f);
Puis définissez le cadre de innerShadowLayer et il devrait étirer l’ombre correctement.
Une version simplifiée utilisant juste un CALayer, dans Swift:
import UIKit
final class FrameView : UIView {
init() {
super.init(frame: CGRect.zero)
backgroundColor = UIColor.white
}
@available(*, unavailable)
required init?(coder decoder: NSCoder) { fatalError("unavailable") }
override func layoutSubviews() {
super.layoutSubviews()
addInnerShadow()
}
private func addInnerShadow() {
let innerShadow = CALayer()
innerShadow.frame = bounds
// Shadow path (1pt ring around bounds)
let path = UIBezierPath(rect: innerShadow.bounds.insetBy(dx: -1, dy: -1))
let cutout = UIBezierPath(rect: innerShadow.bounds).reversing()
path.append(cutout)
innerShadow.shadowPath = path.cgPath
innerShadow.masksToBounds = true
// Shadow properties
innerShadow.shadowColor = UIColor(white: 0, alpha: 1).cgColor // UIColor(red: 0.71, green: 0.77, blue: 0.81, alpha: 1.0).cgColor
innerShadow.shadowOffset = CGSize.zero
innerShadow.shadowOpacity = 1
innerShadow.shadowRadius = 3
// Add
layer.addSublayer(innerShadow)
}
}
Notez que la couche innerShadow ne doit pas avoir de couleur d'arrière-plan opaque, car celle-ci sera rendue devant l'ombre.
Un peu comme un aller-retour, mais cela évite d’avoir à utiliser des images (read: changement facile des couleurs, rayon d’ombre, etc.) et ce n’est que quelques lignes de code.
Ajoutez un UIImageView en tant que première sous-vue de UIView sur laquelle vous souhaitez placer l’ombre portée. J'utilise IB, mais vous pouvez faire la même chose par programme.
En supposant que la référence à UIImageView soit "innerShadow"
`
[[innerShadow layer] setMasksToBounds:YES];
[[innerShadow layer] setCornerRadius:12.0f];
[[innerShadow layer] setBorderColor:[UIColorFromRGB(180, 180, 180) CGColor]];
[[innerShadow layer] setBorderWidth:1.0f];
[[innerShadow layer] setShadowColor:[UIColorFromRGB(0, 0, 0) CGColor]];
[[innerShadow layer] setShadowOffset:CGSizeMake(0, 0)];
[[innerShadow layer] setShadowOpacity:1];
[[innerShadow layer] setShadowRadius:2.0];
Avertissement: vous devez avoir une bordure, sinon l'ombre n'apparaît pas. [UIColor clearColor] ne fonctionne pas. Dans l'exemple, j'utilise une couleur différente, mais vous pouvez la gêner pour qu'elle ait la même couleur que le début de l'ombre. :)
Voir le commentaire de bbrame ci-dessous à propos de la macro UIColorFromRGB
.
Mieux vaut tard que jamais...
Voici une autre approche, probablement pas meilleure que celles déjà publiées, mais c'est simple et agréable -
-(void)drawInnerShadowOnView:(UIView *)view
{
UIImageView *innerShadowView = [[UIImageView alloc] initWithFrame:view.bounds];
innerShadowView.contentMode = UIViewContentModeScaleToFill;
innerShadowView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[view addSubview:innerShadowView];
[innerShadowView.layer setMasksToBounds:YES];
[innerShadowView.layer setBorderColor:[UIColor lightGrayColor].CGColor];
[innerShadowView.layer setShadowColor:[UIColor blackColor].CGColor];
[innerShadowView.layer setBorderWidth:1.0f];
[innerShadowView.layer setShadowOffset:CGSizeMake(0, 0)];
[innerShadowView.layer setShadowOpacity:1.0];
// this is the inner shadow thickness
[innerShadowView.layer setShadowRadius:1.5];
}
Au lieu de dessiner l’ombre intérieure par drawRect ou d’ajouter UIView à la vue. Vous pouvez directement ajouter CALayer à la bordure, par exemple: si je veux un effet d’ombre interne sur le bas de UIView V.
innerShadowOwnerLayer = [[CALayer alloc]init];
innerShadowOwnerLayer.frame = CGRectMake(0, V.frame.size.height+2, V.frame.size.width, 2);
innerShadowOwnerLayer.backgroundColor = [UIColor whiteColor].CGColor;
innerShadowOwnerLayer.shadowColor = [UIColor blackColor].CGColor;
innerShadowOwnerLayer.shadowOffset = CGSizeMake(0, 0);
innerShadowOwnerLayer.shadowRadius = 10.0;
innerShadowOwnerLayer.shadowOpacity = 0.7;
[V.layer addSubLayer:innerShadowOwnerLayer];
Ceci ajoute une ombre interne inférieure pour la cible UIView
Voici une version de Swift, changez startPoint
et endPoint
pour le faire de chaque côté.
let layer = CAGradientLayer()
layer.startPoint = CGPointMake(0.5, 0.0);
layer.endPoint = CGPointMake(0.5, 1.0);
layer.colors = [UIColor(white: 0.1, alpha: 1.0).CGColor, UIColor(white: 0.1, alpha: 0.5).CGColor, UIColor.clearColor().CGColor]
layer.locations = [0.05, 0.2, 1.0 ]
layer.frame = CGRectMake(0, 0, self.view.frame.width, 60)
self.view.layer.insertSublayer(layer, atIndex: 0)
Voici votre solution que j'ai exportée depuis PaintCode :
-(void) drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
//// Shadow Declarations
UIColor* shadow = UIColor.whiteColor;
CGSize shadowOffset = CGSizeMake(0, 0);
CGFloat shadowBlurRadius = 10;
//// Rectangle Drawing
UIBezierPath* rectanglePath = [UIBezierPath bezierPathWithRect: self.bounds];
[[UIColor blackColor] setFill];
[rectanglePath fill];
////// Rectangle Inner Shadow
CGContextSaveGState(context);
UIRectClip(rectanglePath.bounds);
CGContextSetShadowWithColor(context, CGSizeZero, 0, NULL);
CGContextSetAlpha(context, CGColorGetAlpha([shadow CGColor]));
CGContextBeginTransparencyLayer(context, NULL);
{
UIColor* opaqueShadow = [shadow colorWithAlphaComponent: 1];
CGContextSetShadowWithColor(context, shadowOffset, shadowBlurRadius, [opaqueShadow CGColor]);
CGContextSetBlendMode(context, kCGBlendModeSourceOut);
CGContextBeginTransparencyLayer(context, NULL);
[opaqueShadow setFill];
[rectanglePath fill];
CGContextEndTransparencyLayer(context);
}
CGContextEndTransparencyLayer(context);
CGContextRestoreGState(context);
}
Je suis très en retard pour la fête mais je voudrais redonner à la communauté .. C’est une méthode que j’ai écrite pour supprimer l’image d’arrière-plan UITextField, car je fournissais une bibliothèque statique et AUCUNE ressource .. Je l'ai utilisé pour un écran de saisie PIN de quatre instances UITextField pouvant afficher Un caractère brut ou (BOOL) [self isUsingBullets] ou (BOOL) [Auto usingAsterisks] dans ViewController . L'application est pour iPhone/iPhone retina/iPad/iPad Retina, je n'ai donc pas à fournir quatre images ...
#import <QuartzCore/QuartzCore.h>
- (void)setTextFieldInnerGradient:(UITextField *)textField
{
[textField setSecureTextEntry:self.isUsingBullets];
[textField setBackgroundColor:[UIColor blackColor]];
[textField setTextColor:[UIColor blackColor]];
[textField setBorderStyle:UITextBorderStyleNone];
[textField setClipsToBounds:YES];
[textField.layer setBorderColor:[[UIColor blackColor] CGColor]];
[textField.layer setBorderWidth:1.0f];
// make a gradient off-white background
CAGradientLayer *gradient = [CAGradientLayer layer];
CGRect gradRect = CGRectInset([textField bounds], 3, 3); // Reduce Width and Height and center layer
gradRect.size.height += 2; // minimise Bottom shadow, rely on clipping to remove these 2 pts.
gradient.frame = gradRect;
struct CGColor *topColor = [UIColor colorWithWhite:0.6f alpha:1.0f].CGColor;
struct CGColor *bottomColor = [UIColor colorWithWhite:0.9f alpha:1.0f].CGColor;
// We need to use this fancy __bridge object in order to get the array we want.
gradient.colors = [NSArray arrayWithObjects:(__bridge id)topColor, (__bridge id)bottomColor, nil];
[gradient setCornerRadius:4.0f];
[gradient setShadowOffset:CGSizeMake(0, 0)];
[gradient setShadowColor:[[UIColor whiteColor] CGColor]];
[gradient setShadowOpacity:1.0f];
[gradient setShadowRadius:3.0f];
// Now we need to Blur the edges of this layer "so it blends"
// This rasterizes the view down to 4x4 pixel chunks then scales it back up using bilinear filtering...
// it's EXTREMELY fast and looks ok if you are just wanting to blur a background view under a modal view.
// To undo it, just set the rasterization scale back to 1.0 or turn off rasterization.
[gradient setRasterizationScale:0.25];
[gradient setShouldRasterize:YES];
[textField.layer insertSublayer:gradient atIndex:0];
if (self.usingAsterisks) {
[textField setFont:[UIFont systemFontOfSize:80.0]];
} else {
[textField setFont:[UIFont systemFontOfSize:40.0]];
}
[textField setTextAlignment:UITextAlignmentCenter];
[textField setEnabled:NO];
}
J'espère que cela aide quelqu'un comme ce forum m'a aidé.
Consultez le superbe article de Inner Shadows in Quartz de Chris Emery qui explique comment les ombres intérieures sont dessinées par PaintCode et donne un extrait de code net et net:
- (void)drawInnerShadowInContext:(CGContextRef)context
withPath:(CGPathRef)path
shadowColor:(CGColorRef)shadowColor
offset:(CGSize)offset
blurRadius:(CGFloat)blurRadius
{
CGContextSaveGState(context);
CGContextAddPath(context, path);
CGContextClip(context);
CGColorRef opaqueShadowColor = CGColorCreateCopyWithAlpha(shadowColor, 1.0);
CGContextSetAlpha(context, CGColorGetAlpha(shadowColor));
CGContextBeginTransparencyLayer(context, NULL);
CGContextSetShadowWithColor(context, offset, blurRadius, opaqueShadowColor);
CGContextSetBlendMode(context, kCGBlendModeSourceOut);
CGContextSetFillColorWithColor(context, opaqueShadowColor);
CGContextAddPath(context, path);
CGContextFillPath(context);
CGContextEndTransparencyLayer(context);
CGContextRestoreGState(context);
CGColorRelease(opaqueShadowColor);
}
Voici ma solution dans Swift 4.2. Voudriez-vous essayer?
final class ACInnerShadowLayer : CAShapeLayer {
var innerShadowColor: CGColor? = UIColor.black.cgColor {
didSet { setNeedsDisplay() }
}
var innerShadowOffset: CGSize = .zero {
didSet { setNeedsDisplay() }
}
var innerShadowRadius: CGFloat = 8 {
didSet { setNeedsDisplay() }
}
var innerShadowOpacity: Float = 1 {
didSet { setNeedsDisplay() }
}
override init() {
super.init()
masksToBounds = true
contentsScale = UIScreen.main.scale
setNeedsDisplay()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func draw(in ctx: CGContext) {
ctx.setAllowsAntialiasing(true)
ctx.setShouldAntialias(true)
ctx.interpolationQuality = .high
let colorspace = CGColorSpaceCreateDeviceRGB()
var rect = bounds
var radius = cornerRadius
if borderWidth != 0 {
rect = rect.insetBy(dx: borderWidth, dy: borderWidth)
radius -= borderWidth
radius = max(radius, 0)
}
let innerShadowPath = UIBezierPath(roundedRect: rect, cornerRadius: radius).cgPath
ctx.addPath(innerShadowPath)
ctx.clip()
let shadowPath = CGMutablePath()
let shadowRect = rect.insetBy(dx: -rect.size.width, dy: -rect.size.width)
shadowPath.addRect(shadowRect)
shadowPath.addPath(innerShadowPath)
shadowPath.closeSubpath()
if let innerShadowColor = innerShadowColor, let oldComponents = innerShadowColor.components {
var newComponets = Array<CGFloat>(repeating: 0, count: 4) // [0, 0, 0, 0] as [CGFloat]
let numberOfComponents = innerShadowColor.numberOfComponents
switch numberOfComponents {
case 2:
newComponets[0] = oldComponents[0]
newComponets[1] = oldComponents[0]
newComponets[2] = oldComponents[0]
newComponets[3] = oldComponents[1] * CGFloat(innerShadowOpacity)
case 4:
newComponets[0] = oldComponents[0]
newComponets[1] = oldComponents[1]
newComponets[2] = oldComponents[2]
newComponets[3] = oldComponents[3] * CGFloat(innerShadowOpacity)
default:
break
}
if let innerShadowColorWithMultipliedAlpha = CGColor(colorSpace: colorspace, components: newComponets) {
ctx.setFillColor(innerShadowColorWithMultipliedAlpha)
ctx.setShadow(offset: innerShadowOffset, blur: innerShadowRadius, color: innerShadowColorWithMultipliedAlpha)
ctx.addPath(shadowPath)
ctx.fillPath(using: .evenOdd)
}
}
}
}
Il y a du code ici qui peut le faire pour vous. Si vous modifiez le calque dans votre vue (en remplaçant + (Class)layerClass
) par JTAInnerShadowLayer, vous pouvez définir l'ombre interne du calque d'indent dans votre méthode init et le travail sera fait pour vous. Si vous souhaitez également dessiner le contenu d'origine, veillez à appeler setDrawOriginalImage:yes
sur le calque d'indentation. Il y a un article de blog sur la façon dont cela fonctionne ici .
Utilisation de la couche de dégradé:
UIView * mapCover = [UIView new];
mapCover.frame = map.frame;
[view addSubview:mapCover];
CAGradientLayer * vertical = [CAGradientLayer layer];
vertical.frame = mapCover.bounds;
vertical.colors = [NSArray arrayWithObjects:(id)[UIColor whiteColor].CGColor,
(id)[[UIColor whiteColor] colorWithAlphaComponent:0.0f].CGColor,
(id)[[UIColor whiteColor] colorWithAlphaComponent:0.0f].CGColor,
(id)[UIColor whiteColor].CGColor, nil];
vertical.locations = @[@0.01,@0.1,@0.9,@0.99];
[mapCover.layer insertSublayer:vertical atIndex:0];
CAGradientLayer * horizontal = [CAGradientLayer layer];
horizontal.frame = mapCover.bounds;
horizontal.colors = [NSArray arrayWithObjects:(id)[UIColor whiteColor].CGColor,
(id)[[UIColor whiteColor] colorWithAlphaComponent:0.0f].CGColor,
(id)[[UIColor whiteColor] colorWithAlphaComponent:0.0f].CGColor,
(id)[UIColor whiteColor].CGColor, nil];
horizontal.locations = @[@0.01,@0.1,@0.9,@0.99];
horizontal.startPoint = CGPointMake(0.0, 0.5);
horizontal.endPoint = CGPointMake(1.0, 0.5);
[mapCover.layer insertSublayer:horizontal atIndex:0];
Avec le InnerShadowLayer
décrit, vous pouvez également activer les ombres intérieures pour des arêtes spécifiques uniquement, à l'exclusion des autres. (par exemple, vous pouvez activer les ombres intérieures uniquement sur les bords gauche et supérieur de votre vue)
Vous pouvez ensuite ajouter un InnerShadowLayer
à votre vue en utilisant:
init(...) {
// ... your initialization code ...
super.init(frame: .zero)
layer.addSublayer(shadowLayer)
}
public override func layoutSubviews() {
super.layoutSubviews()
shadowLayer.frame = bounds
}
InnerShadowLayer
implémentation/// Shadow is a struct defining the different kinds of shadows
public struct Shadow {
let x: CGFloat
let y: CGFloat
let blur: CGFloat
let opacity: CGFloat
let color: UIColor
}
/// A layer that applies an inner shadow to the specified edges of either its path or its bounds
public class InnerShadowLayer: CALayer {
private let shadow: Shadow
private let Edge: UIRectEdge
public init(shadow: Shadow, Edge: UIRectEdge) {
self.shadow = shadow
self.Edge = Edge
super.init()
setupShadow()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
public override func layoutSublayers() {
updateShadow()
}
private func setupShadow() {
shadowColor = shadow.color.cgColor
shadowOpacity = Float(shadow.opacity)
shadowRadius = shadow.blur / 2.0
masksToBounds = true
}
private func updateShadow() {
shadowOffset = {
let topWidth: CGFloat = 0
let leftWidth = Edge.contains(.left) ? shadow.y / 2 : 0
let bottomWidth: CGFloat = 0
let rightWidth = Edge.contains(.right) ? -shadow.y / 2 : 0
let topHeight = Edge.contains(.top) ? shadow.y / 2 : 0
let leftHeight: CGFloat = 0
let bottomHeight = Edge.contains(.bottom) ? -shadow.y / 2 : 0
let rightHeight: CGFloat = 0
return CGSize(width: [topWidth, leftWidth, bottomWidth, rightWidth].reduce(0, +),
height: [topHeight, leftHeight, bottomHeight, rightHeight].reduce(0, +))
}()
let insets = UIEdgeInsets(top: Edge.contains(.top) ? -bounds.height : 0,
left: Edge.contains(.left) ? -bounds.width : 0,
bottom: Edge.contains(.bottom) ? -bounds.height : 0,
right: Edge.contains(.right) ? -bounds.width : 0)
let path = UIBezierPath(rect: bounds.inset(by: insets))
let cutout = UIBezierPath(rect: bounds).reversing()
path.append(cutout)
shadowPath = path.cgPath
}
}
ce code a fonctionné pour moi
class InnerDropShadowView: UIView {
override func draw(_ rect: CGRect) {
//Drawing code
let context = UIGraphicsGetCurrentContext()
//// Shadow Declarations
let shadow: UIColor? = UIColor.init(hexString: "a3a3a3", alpha: 1.0) //UIColor.black.withAlphaComponent(0.6) //UIColor.init(hexString: "d7d7da", alpha: 1.0)
let shadowOffset = CGSize(width: 0, height: 0)
let shadowBlurRadius: CGFloat = 7.5
//// Rectangle Drawing
let rectanglePath = UIBezierPath(rect: bounds)
UIColor.groupTableViewBackground.setFill()
rectanglePath.fill()
////// Rectangle Inner Shadow
context?.saveGState()
UIRectClip(rectanglePath.bounds)
context?.setShadow(offset: CGSize.zero, blur: 0, color: nil)
context?.setAlpha((shadow?.cgColor.alpha)!)
context?.beginTransparencyLayer(auxiliaryInfo: nil)
do {
let opaqueShadow: UIColor? = shadow?.withAlphaComponent(1)
context?.setShadow(offset: shadowOffset, blur: shadowBlurRadius, color: opaqueShadow?.cgColor)
context!.setBlendMode(.sourceOut)
context?.beginTransparencyLayer(auxiliaryInfo: nil)
opaqueShadow?.setFill()
rectanglePath.fill()
context!.endTransparencyLayer()
}
context!.endTransparencyLayer()
context?.restoreGState()
}
}