EDIT:Dessiner un UIView arrondi avec gradient et ombre portée
J'ai finalement trouvé une vraie solution simple à ce problème, en utilisant la classe CAGradientLayer, et les fonctionnalités de dessin CALayer.
Ole Begemann a publié un excellent wrapper UIView pour la classe CAGradientLayer nommée OBGradientView.
Cette classe vous permet de créer facilement un gradient UIView dans votre application.
Vous utilisez ensuite les fonctionnalités de dessin CALayer ajouter les coins arrondis et déposez les valeurs d'ombre:
// Create the gradient view
OBGradientView *gradient = [[OBGradientView alloc] initWithFrame:someRect];
NSArray *colors = [NSArray arrayWithObjects:[UIColor redColor], [UIColor yellowColor], nil];
gradient.colors = colors;
// Set rounded corners and drop shadow
gradient.layer.cornerRadius = 5.0;
gradient.layer.shadowColor = [UIColor grayColor].CGColor;
gradient.layer.shadowOpacity = 1.0;
gradient.layer.shadowOffset = CGSizeMake(2.0, 2.0);
gradient.layer.shadowRadius = 3.0;
[self.view addSubview:gradient];
[gradient release];
Ne pas oublier d'ajouter le cadre QuartzCore à votre projet.
QUESTION ORIGINAL:
Je travaille sur un contrôle personnalisé qui est un bouton rectangle arrondi, rempli d'un gradient linéaire, et ayant une ombre portée. J'ai rempli les deux premières étapes en utilisant cette réponse: link text
Mon problème est maintenant d'ajouter une ombre portée sous la forme résultante. En fait, le contexte a été coupé au rectangle arrondi, donc quand j'utilise la fonction CGContextSetShadow, il ne le dessine pas.
J'ai essayé de résoudre ce problème en dessinant deux fois le rectangle arrondi, d'abord avec une couleur unie, afin de dessiner l'ombre, puis de la redessiner avec le dégradé.
Il a travaillé un peu, mais je peux encore voir quelques pixels dans les coins de la forme résultant du premier tirage au sort avec une couleur unie, comme vous pouvez le voir sur cette version zoomée:
http://img269.imageshack.us/img269/6489/capturedcran20100701192.png
il est presque bon, mais pas encore parfait ...
Voici mon -drawRect: la mise en œuvre:
static void addRoundedRectToPath(CGContextRef context, CGRect rect, float ovalWidth, float ovalHeight)
{
float fw, fh;
if (ovalWidth == 0 || ovalHeight == 0) {
CGContextAddRect(context, rect);
return;
}
CGContextSaveGState(context);
CGContextTranslateCTM (context, CGRectGetMinX(rect), CGRectGetMinY(rect));
CGContextScaleCTM (context, ovalWidth, ovalHeight);
fw = CGRectGetWidth (rect)/ovalWidth;
fh = CGRectGetHeight (rect)/ovalHeight;
CGContextMoveToPoint(context, fw, fh/2);
CGContextAddArcToPoint(context, fw, fh, fw/2, fh, 1);
CGContextAddArcToPoint(context, 0, fh, 0, fh/2, 1);
CGContextAddArcToPoint(context, 0, 0, fw/2, 0, 1);
CGContextAddArcToPoint(context, fw, 0, fw, fh/2, 1);
CGContextClosePath(context);
CGContextRestoreGState(context);
}
- (void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGSize shadowOffset = CGSizeMake(10.0, 10.0);
CGFloat blur = 5.0;
rect.size.width -= shadowOffset.width + blur;
rect.size.height -= shadowOffset.height + blur;
CGContextSaveGState(context);
addRoundedRectToPath(context, rect, _radius, _radius);
CGContextSetShadow (context, shadowOffset, blur);
CGContextDrawPath(context, kCGPathFill);
CGContextRestoreGState(context);
addRoundedRectToPath(context, rect, _radius, _radius);
CGContextClip(context);
CGFloat colors[] =
{
_gradientStartColor.red, _gradientStartColor.green, _gradientStartColor.blue, _gradientStartColor.alpha,
_gradientEndColor.red, _gradientEndColor.green, _gradientEndColor.blue, _gradientEndColor.alpha
};
size_t num_locations = 2;
CGFloat locations[2] = { 0.0, 1.0 };
CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
CGGradientRef gradient = CGGradientCreateWithColorComponents(rgb, colors, locations, num_locations);
CGRect currentBounds = self.bounds;
CGPoint gStartPoint = CGPointMake(CGRectGetMidX(currentBounds), 0.0f);
CGPoint gEndPoint = CGPointMake(CGRectGetMidX(currentBounds), CGRectGetMaxY(currentBounds));
CGContextDrawLinearGradient(context, gradient, gStartPoint, gEndPoint, 0);
CGColorSpaceRelease(rgb);
CGGradientRelease(gradient);
}
Toutes les idées sur la façon de le faire d'une autre manière?
Merci!
Merci beno pour cette explication très détaillée! Votre exemple fonctionne parfaitement. Je voudrais juste corriger votre déclaration CGGradientRef de CGGradientRef * normalGradient à CGGradientRef normalGradient. –
Pouvez-vous expliquer comment les lignes tangentes et les points sont créés à partir des arguments? Je ne comprends pas comment vous pouvez créer deux lignes et deux points à partir de 4 arguments ... – ryyst
@super_tomtom quelqu'un peut-il expliquer comment cela fonctionne? J'ai sous-classes un UIView personnalisé et fait cette fonction c'est drawRect override mais je n'ai toujours pas de coins arrondis ou ombre portée? –