Pour quiconque se demande comment dessiner une ombre intérieure en utilisant Core Graphics selon la suggestion de Costique, voici comment: (sur iOS, ajustez au besoin)
Dans votre drawRect: method ...
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, il y a essentiellement les étapes suivantes:
- Créez votre chemin
- Définissez la couleur de remplissage souhaitée, ajoutez ce chemin au contexte et remplissez le contexte
- Créez maintenant un rectangle plus grand qui peut délimiter le chemin visible. Avant de fermer ce chemin, ajoutez le chemin visible. Fermez ensuite le tracé afin de créer une forme dont le tracé visible en est soustrait. Vous voudrez peut-être étudier les méthodes de remplissage (enroulement non nul de pair / impair) en fonction de la façon dont vous avez créé ces chemins. Essentiellement, pour obtenir les sous-chemins à «soustraire» lorsque vous les additionnez, vous devez les dessiner (ou plutôt les construire) dans des directions opposées, l'une dans le sens des aiguilles d'une montre et l'autre dans le sens inverse.
- Ensuite, vous devez définir votre chemin visible comme chemin de détourage sur le contexte, afin de ne rien dessiner en dehors de celui-ci à l'écran.
- Ensuite, configurez l'ombre sur le contexte, qui comprend le décalage, le flou et la couleur.
- Remplissez ensuite la grande forme avec le trou dedans. La couleur n'a pas d'importance, car si vous avez tout fait correctement, vous ne verrez pas cette couleur, juste l'ombre.