2012-12-06 9 views
7

Próbuję przesłonić metodę UIView na drawRect: w moim widoku niestandardowym. Jednak moim zdaniem ma promień granica określona jako:UIView nadpisywanie funkcji drawRect powoduje, że widok nie jest zgodny z maskamiToBounds

sub = [[[NSBundle mainBundle] loadNibNamed:@"ProfileView" owner:self options:nil] objectAtIndex:0]; 
    [self addSubview:sub]; 
    [sub setUserInteractionEnabled:YES]; 
    [self setUserInteractionEnabled:YES]; 
    CALayer *layer = sub.layer; 
    layer.masksToBounds = YES; 
    layer.borderWidth = 5.0; 
    layer.borderColor = [UIColor whiteColor].CGColor; 
    layer.cornerRadius = 30.0; 

To działa doskonale i umieszcza piękny granicy z promieniem obramowanie wokół moim zdaniem (nie przeszkadza ukośne/prosty białe linie na plecach, mają nic wspólnego z tym poglądem):

correct one

jednak gdy próbuję zastąpić metodę drawRect: moim zdaniem, widzę czarne tło nie maskowania do granic. Nie rób nic (obecnie), tutaj jest mój kod:

-(void)drawRect:(CGRect)rect{ 
    [super drawRect:rect]; 
} 

A oto wynik:

incorrect one

mam nic ale metoda wyciągania zmieniło. W jaki sposób mogę przesłonić metodę rysowania, zachowując mój widok na maskę promienia narożnika? Czy jest to błąd w systemie iOS, czy też coś mi brakuje?

Odpowiedz

3

Nie znam pełnej odpowiedzi, ale wiem, że implementacja UIView w wersji drawLayer:inContext: działa inaczej w zależności od tego, czy zaimplementowano drawRect:, czy nie. Być może maskowanie/przycinanie do granic jest jedną z tych rzeczy, które robi inaczej.

Można spróbować rozwiązać problem na kilka sposobów:

  • dokonać tło transparent:

    layer.backgroundColor = [UIColor clearColor].CGColor; 
    
  • clip siebie wewnątrz zwyczaju drawRect::

    - (void)drawRect:(CGRect)rect { 
        [[UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:30.0] addClip]; 
        [image drawInRect:rect]; // or whatever 
    } 
    
  • Wyraźnie wytnij narożniki:

    CGContextBeginPath(c); 
    CGContextAddArc(c, r, r, r, M_PI, 3*M_PI_2, 0); 
    CGContextAddLineToPoint(c, 0, 0); 
    CGContextClosePath(c); 
    CGContextClip(c); 
    [[UIColor grayColor] setFill]; 
    UIRectFill(rect); 
    

Wygrałem te 2 ostatnie propozycje z tej wielkiej prezentacji z WWDC 2010: Advanced Performance Optimization on iPhone OS (wideo wymienione w this index page - irytująco, nie bezpośredni link).

1

Prawdopodobnie nie powinno wywołać

[super drawRect:rect] 

wewnątrz drawRect. Apple says że:

Jeśli podklasy UIView bezpośrednio, implementacja tej metody nie trzeba zadzwonić Super. Jeśli jednak podklasujesz inną klasę widoku, powinieneś zadzwonić super w pewnym momencie implementacji .

Wygląda na to, że wywołanie metody super powoduje dziwne zachowanie.

2

To jest stare pytanie, ale ostatnio czytałem użyteczny wpis na blogu pod tytułem Abusing UIView. W nim autor odradza przesłonięcie drawRect, aby zrobić coś w rodzaju dodania obramowania, gdy są inne sposoby na zrobienie tego. Mówi,

Przesłanianie drawRect: powoduje trafienie wydajności. Nie profilowałem tego, , więc nie wiem, czy jest to znacząca wydajność w normalnych warunkach (prawdopodobnie nie), ale w większości przypadków ludzie, którzy przesłaniają drawRect: mogą osiągnąć to, czego chcą znacznie łatwiej przez ustawienie właściwości we właściwości warstwy widoku. Jeśli trzeba narysować kontur wokół myślą, oto jak można to zrobić:

#import <QuartzCore/QuartzCore.h> 

- (id)initWithFrame:(CGRect)frame { 
    self = [super initWithFrame:frame]; 
    if (self) { 
     self.layer.borderWidth = 2.f; 
     self.layer.borderColor = [UIColor redColor].CGColor; 
    } 
    return self; 

Zdaję sobie sprawę, to prawdopodobnie nie rozwiąże problemu czarnym tle pokazano poprzez. To tylko coś innego do przemyślenia.

1

Ustawianie

opaque = false // NO for ObjC 

na widoku rozwiązuje problem.

+0

To jest poprawna odpowiedź. – Randy

Powiązane problemy