2013-07-23 15 views
11

Voglio disegnare del testo nella mia sottoclasse su UIView in modo che il testo sia tagliato fuori dalla forma e lo sfondo dietro la vista sia visibile, proprio come nel logo OSX Mavericks trovato here.Sottoclasse UIView di iOS, disegnare il testo trasparente sullo sfondo

Direi che sono più uno sviluppatore iOS intermedio/precoce, quindi sentitevi libero di lanciarmi qualche soluzione pazzesca. Mi aspetterei che dovrei scavalcare lo drawRect per fare questo.

Grazie ragazzi!

EDIT:

Devo dire che il mio primo tentativo stava facendo il testo [UIColor clearColor] che non ha funzionato dal momento che solo impostare il componente alfa del testo a 0, che ha appena mostrato la vista attraverso il testo.

+2

Giusto per chiarire che stai utilizzando Core Text per disegnare e non UILabels? – feliun

+0

Sì, è vero. – barndog

risposta

15

Disclaimer: Sto scrivendo questo senza test, quindi perdonami se sbaglio qui.

Si dovrebbe ottenere quello che ti serve per questi due passaggi:

  1. Creare un CATextLayer con la dimensione della visualizzazione, impostare il backgroundColor di essere pienamente trasparente e foregroundColor a essere opaco (da [UIColor colorWithWhite:0 alpha:1] e [UIColor colorWithWhite:0 alpha:0]. quindi impostare la proprietà string alla stringa che si desidera rendere, font e fontSize ecc

  2. impostare la maschera del livello di immagine per questo livello: myView.layer.mask = textLayer. Dovrai importare QuartzCore per accedere allo CALayer della tua vista.

Si noti che è possibile passare dal colore opaco a quello trasparente nel primo passaggio.

Modifica: In effetti, Noah aveva ragione. Per superare questo problema, ho utilizzato CoreGraphics con la modalità di fusione kCGBlendModeDestinationOut.

In primo luogo, una vista di esempio che mostra che funziona davvero:

@implementation TestView 

- (id)initWithFrame:(CGRect)frame { 
    if (self = [super initWithFrame:frame]) { 
    self.backgroundColor = [UIColor clearColor]; 
    } 
    return self; 
} 

- (void)drawRect:(CGRect)rect { 
    [[UIColor redColor] setFill]; 
    UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:10]; 
    [path fill]; 

    CGContextRef context = UIGraphicsGetCurrentContext(); 
    CGContextSaveGState(context); { 
    CGContextSetBlendMode(context, kCGBlendModeDestinationOut); 
    [@"Hello!" drawAtPoint:CGPointZero withFont:[UIFont systemFontOfSize:24]]; 
    } CGContextRestoreGState(context); 
} 

@end 

Dopo aver aggiunto questo al vostro controller della vista, si vedrà la vista dietro TestView dove Hello! è disegnato.

Perché fa questo lavoro:

Il metodo di fusione è definita come R = D*(1 - Sa), il che significa che abbiamo bisogno di valori alfa opposte rispetto al livello di mask ho suggerito in precedenza. Pertanto, tutto ciò che devi fare è disegnare con un colore opaco e questo sarà sottratto dalle cose che hai disegnato sulla vista in anticipo.

+0

Ciò causerà solo il mascheramento della vista con il testo, non il taglio del testo. Le maschere di livello usano l'opacità del livello maschera. –

+0

Se inverti l'alfa del livello, dovrebbe lasciare la vista e tagliare il testo, no? Quindi, invece di disegnare sulla vista stessa, disegnare sul livello maschera. – StatusReport

+0

"Invertire l'alfa del livello" non è una cosa. Se si imposta un livello di testo con un colore di sfondo a tinta unita e un colore di testo trasparente, il suo alfa sarà un rettangolo pieno. –

1

In realtà ho capito come farlo da solo, ma la risposta di @ StatusReport è completamente valida e funziona così com'è ora.

Ecco come ho fatto:

-(void)drawRect:(CGRect)rect{ 
    CGContextRef context = UIGraphicsGetCurrentContext(); 
    [[UIColor darkGrayColor]setFill]; //this becomes the color of the alpha mask 
    CGContextFillRect(context, rect); 
    CGContextSaveState(context); 
    [[UIColor whiteColor]setFill]; 
    //Have to flip the context since core graphics is done in cartesian coordinates 
    CGContextTranslateCTM(context, 0, rect.size.height); 
    CGContextScaleCTM(context, 1.0, -1.0); 
    [textToDraw drawInRect:rect withFont:[UIFont fontWithName:@"HelveticaNeue-Thin" size:40]; 
    CGContextRestoreGState(context); 
    CGImageRef alphaMask = CGBitmapContextCreateImage(context); 
    [[UIColor whiteColor]setFill]; 
    CGContextFillRect(context, rect); 
    CGContextSaveGState(context); 
    CGContentClipToMask(context, rect, alphaMask); 
    [backgroundImage drawInRect:rect]; 
    CGContextRestoreGState(context); 
    CGImageRelease(alphaMask); 
} 

- (void)setTextToDraw:(NSString*)text{ 
    if(text != textToDraw){ 
     textToDraw = text; 
     [self setNeedsDisplay]; 
    } 
} 

devo una dichiarazione @synthesize per textToDraw così ho potuto ignorare il setter e chiamare [self setNeedsDisplay]. Non sono sicuro che sia del tutto necessario o no.

Sono sicuro che questo ha alcuni errori di battitura, ma posso assicurarvi che la versione con controllo ortografico funziona bene.