EDIT fallen:eine abgerundete UIView mit Steigung Zeichnen und Schatten
finde ich endlich eine echte einfache Lösung für dieses Problem, die CAGradientLayer-Klasse und die CALayer Zeichnung Funktionalitäten.
Ole Begemann veröffentlichte einen großen UIView-Wrapper für die CAGradientLayer-Klasse OBGradientView.
Mit dieser Klasse können Sie auf einfache Weise in Ihrer Anwendung eine UIView mit Verlauf erstellen.
Sie dann verwenden, um die CALayer Zeichnung Funktionalitäten die abgerundeten Ecken hinzuzufügen und Schattenwerte fallen:
// 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];
Vergessen Sie nicht, den Rahmen zu Quartz Projekt hinzuzufügen.
ursprüngliche Frage:
Ich habe auf einem kundenspezifischen Steuerung arbeitet, die ein abgerundetes Rechteck Knopf ist, mit einem linearen Gradienten gefüllt ist, und einen Schlagschatten aufweisen. Ich habe die ersten beiden Schritte mit dieser Antwort ausgefüllt: link text
Mein Problem ist jetzt, einen Schlagschatten unter der resultierenden Form hinzuzufügen. Eigentlich wurde der Kontext auf den abgerundeten rect-Pfad abgeschnitten. Wenn ich also die CGContextSetShadow-Funktion verwende, wird sie nicht gezeichnet.
Ich habe versucht, dieses Problem zu lösen, indem ich das gerundete Rechteck zweimal zuerst mit einer einfachen Farbe zeichne, so dass es den Schatten zeichnet und dann mit der Gradientenfüllung neu zeichnet.
Es funktionierte irgendwie, aber ich kann noch ein paar Pixel an den Ecken der Form aus der ersten Ziehung mit einer einfachen Farbe sehen, wie Sie auf dieser gezoomte Version sehen:
http://img269.imageshack.us/img269/6489/capturedcran20100701192.png
es ist fast gut, aber noch nicht perfekt ...
Hier ist meine -drawRect: Umsetzung:
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);
}
Irgendwelche Ideen auf, wie man Tun Sie das auf andere Weise?
Danke!
Vielen Dank für diese sehr detaillierte Erklärung! Ihr Beispiel funktioniert perfekt. Ich würde nur Ihre CGGradientRef-Deklaration von CGGradientRef * normalGradient zu CGGradientRef normalGradient korrigieren. –
Können Sie erklären, wie die Tangenten und Punkte aus den Argumenten erzeugt werden? Ich verstehe nicht, wie Sie zwei Zeilen und zwei Punkte aus 4 Argumente erstellen können ... – ryyst
@super_tomtom kann jemand erklären, wie das funktioniert? Ich habe eine benutzerdefinierte UIView-Klasse unterklassifiziert und diese Funktion zu ihrer drawRect-Überschreibung gemacht, aber ich bekomme immer noch keine abgerundeten Ecken oder Schlagschatten? –