Applicando un tratto a un rettangolo arrotondato in core-grafici
-
24-09-2019 - |
Domanda
Ho un gradiente che ha gli angoli arrotondati che ho un uso per una consuetudine UITableViewCell sfondo. Sto cercando di applicare un tratto al percorso, ma non riesco a farlo, e non riesco a vedere dove sto andando male.
CGFloat minx = CGRectGetMinX(rect) , midx = CGRectGetMidX(rect), maxx = CGRectGetMaxX(rect) ;
CGFloat miny = CGRectGetMinY(rect) , maxy = CGRectGetMaxY(rect) ;
minx = minx + 1;
miny = miny ;
maxx = maxx - 1;
maxy = maxy - 1;
CGContextMoveToPoint(c, minx, miny);
CGContextAddArcToPoint(c, minx, maxy, midx, maxy, kDefaultMargin);
CGContextAddArcToPoint(c, maxx, maxy, maxx, miny, kDefaultMargin);
CGContextAddLineToPoint(c, maxx, miny);
CGContextAddLineToPoint(c, minx, miny);
// Fill and stroke the path
CGContextClip(c);
CGContextStrokePath(c);
CGFloat locations[2] = { 0.0, 1.0 };
CGFloat mycomponents[8] = TABLE_CELL_BACKGROUND;
CGColorSpaceRef myColorspace = CGColorSpaceCreateDeviceRGB();
CGGradientRef myGradient = CGGradientCreateWithColorComponents(myColorspace, mycomponents, locations, 2);
CGContextDrawLinearGradient(c, myGradient, CGPointMake(minx,miny), CGPointMake(minx,maxy), 0);
CGGradientRelease(myGradient);
CGColorSpaceRelease(myColorspace);
Questo codice arrotonda destra rettangolo e applica il gradiente, ma non fa ictus la riga. Dove è il mio errore?
Modifica
Secondo le raccomandazioni del SUBW, ho cambiato il codice per essere:
CGContextRef c = UIGraphicsGetCurrentContext();
CGColorSpaceRef myColorspace = CGColorSpaceCreateDeviceRGB();
CGGradientRef myGradient = nil;
CGFloat components[8] = TABLE_CELL_BACKGROUND;
CGContextSetFillColorWithColor(c, [[UIColor redColor] CGColor]);
CGContextSetStrokeColorWithColor(c, [[UAColor redColor] CGColor]);
CGContextSetLineWidth(c, 2);
CGFloat minx = CGRectGetMinX(rect) , midx = CGRectGetMidX(rect), maxx = CGRectGetMaxX(rect) ;
CGFloat miny = CGRectGetMinY(rect) , maxy = CGRectGetMaxY(rect) ;
minx = minx + 1;
miny = miny ;
maxx = maxx - 1;
maxy = maxy - 1;
CGContextMoveToPoint(c, minx, miny);
CGContextAddArcToPoint(c, minx, maxy, midx, maxy, kDefaultMargin);
CGContextAddArcToPoint(c, maxx, maxy, maxx, miny, kDefaultMargin);
CGContextAddLineToPoint(c, maxx, miny);
CGContextAddLineToPoint(c, minx, miny);
// Fill and stroke the path
CGContextSaveGState(c);
CGContextClip(c);
CGFloat locations[2] = { 0.0, 1.0 };
CGFloat mycomponents[8] = TABLE_CELL_BACKGROUND;
CGColorSpaceRef myColorspace = CGColorSpaceCreateDeviceRGB();
myGradient = CGGradientCreateWithColorComponents(myColorspace, mycomponents, locations, 2);
CGContextDrawLinearGradient(c, myGradient, CGPointMake(minx,miny), CGPointMake(minx,maxy), 0);
CGContextRestoreGState(c);
CGContextStrokePath(c);
Ma il rect viene fuori come questo ...
... senza alcun confine. Se cambio la CGContextStrokePath(c)
essere CGContextStrokeRect(c, rect)
, gli spettacoli corsa verso l'alto (ho reso rosso per chiarimenti). Ma in qualche modo, quando accarezzando il percorso, non sto ottenendo alcun ictus: (
Soluzione
In risposta al tuo codice rivisto, cito la documentazione:
A differenza del percorso corrente, il tracciato di ritaglio corrente è parte dello stato grafico. Pertanto, per ri-allargare l'area verniciabile ripristinando il tracciato di ritaglio a uno stato precedente, è necessario salvare lo stato grafico prima di ritagliare e ripristinare lo stato grafico dopo aver completato qualsiasi disegno ritagliato.
Dopo aver determinato il nuovo percorso ritaglio, la funzione resetta percorso attuale del contesto di un percorso vuoto.
Quindi, il percorso di disegno corrente è non parte dello stato grafico. Quindi, ecco quello che stai facendo:
- percorso disegno Costruire
- Salva gstate
- Aggiungi percorso disegno corrente al tracciato di ritaglio; percorso chiaro disegno corrente
- Draw gradiente
- Restore gstate (precedente percorso di clipping è ripristinato; percorso elaborazione rimane vuota)
- Corsa niente
La soluzione è quella di disegnare il percorso in un oggetto CGPath, quindi aggiungerlo come percorso di corrente sia prima clipping (dopo il salvataggio del gstate) e prima accarezzare.
Si dovrebbe anche decidere se si desidera che questo sia una corsa esterna, una corsa interna, o un colpo centrato. Per un colpo centrato, ictus mentre non è tagliato. Per una traccia interna, ictus mentre ritagliato. Per una corsa esterno, invertire il percorso, quindi clip, quindi ictus. Ti consigliamo di raddoppiare la larghezza della linea per entrambe le ultime due forme, in quanto sarete i fotogrammi delle metà della corsa.
Se cambio la
CGContextStrokePath(c)
essereCGContextStrokeRect(c, rect)
, gli spettacoli corsa fino.
Poiché tale funzione aggiunge un percorso di detto rettangolo al percorso disegno corrente prima di accarezzare.
Altri suggerimenti
Non è sicuro, ma forse si sta dipingendo il gradiente sopra la corsa?
Si sta disegnando sia il gradiente di sopra della corsa, e / o di ritaglio la regione che ictus.
Credo che il seguente lavoro potrebbe meglio:
CGContextSaveGState(c);
CGContextClip(c);
//gradient drawing stuff
CGContextRestoreGState(c);
CGContextStrokePath(c);
Naturalmente, si hanno anche per impostare il colore del tratto e la larghezza in modo corretto.