EDIT:Disegnare un UIView arrotondato con gradiente e ombra
ho finalmente trovato un vero semplice soluzione a questo problema, utilizzando la classe CAGradientLayer, e le funzionalità di disegno CALayer.
Ole Begemann ha rilasciato un grande wrapper UIView per la classe CAGradientLayer denominata OBGradientView.
Questa classe consente di creare facilmente un UIView a gradiente nell'applicazione.
È quindi utilizzare i CALayer funzionalità di disegno per aggiungere gli angoli arrotondati e rilasciare i valori d'ombra:
// 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];
Non dimenticate di aggiungere il quadro QuartzCore al progetto.
DOMANDA ORIGINALE:
Ho lavorato su un controllo personalizzato che un pulsante arrotondato rettangolo, riempito con un gradiente lineare, e avendo un'ombra. Ho completato i due primi passi utilizzando questa risposta: link text
Il mio problema è ora di aggiungere un'ombra esterna sotto la forma risultante. In realtà, il contesto è stato ritagliato nel percorso rect arrotondato, quindi quando uso la funzione CGContextSetShadow, non lo disegna.
Ho provato a risolvere questo problema disegnando il rettangolo arrotondato due volte, prima con un colore semplice, in modo da disegnare l'ombra e quindi ridisegnarlo con il riempimento sfumato.
kinda funzionato, ma posso ancora vedere qualche pixel agli angoli della forma risultante dal primo pareggio con un colore uniforme, come si può vedere in questa versione ingrandita:
http://img269.imageshack.us/img269/6489/capturedcran20100701192.png
E 'quasi buono, ma non ancora perfetto ...
Ecco la mia -drawRect: implementazione:
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);
}
Tutte le idee su come fai questo in un altro modo?
Grazie!
Grazie mille per questa spiegazione molto dettagliata! Il tuo esempio funziona perfettamente. Correggerei semplicemente la dichiarazione CGGradientRef da CGGradientRef * normalGradient a CGGradientRef normalGradient. –
Puoi spiegare come vengono create le linee e i punti tangenti dagli argomenti? Non capisco come sia possibile creare due righe e due punti da 4 argomenti ... – ryyst
@super_tomtom qualcuno può spiegare come funziona? Ho sottoclassi un UIView personalizzato e ho fatto questa funzione è drawRect override ma non ho ancora angoli arrotondati o drop shadow? –