2016-07-27 17 views
5

Ich verwende Schatten auf eine UITableViewCell mit CALayer.CALayer shadow in UITableViewCell Falsch gezeichnet

Hier ist mein Code:

- (void)addShadowToView:(UIView *)view 
{ 
    // shadow 
    view.layer.shadowColor = [[UIColor colorWithWhite:0.0f alpha:0.1f] CGColor]; 
    view.layer.shadowOpacity = 1.0f; 
    view.layer.shadowOffset = CGSizeMake(0.0f, 3.0f); 
    view.layer.shadowRadius = 6.0f; 

    CGRect shadowFrame = view.layer.bounds; 
    CGPathRef shadowPath = [UIBezierPath bezierPathWithRect:shadowFrame].CGPath; 
    view.layer.shadowPath = shadowPath; 
} 

Das Problem ist, dass für einige tableviewcells, wird der Schatten nicht über die gesamte Breite der Zelle erstrecken. Für einige Zellen wäre es korrekt, für andere wäre es fehlerhaft. Ich bemerke, dass die Rotation des Geräts auch Auswirkungen hat, und das erneute Laden der Daten der Tabellenansicht löst es manchmal.

Was ist der beste Weg, um dieses Problem zu beheben (und damit ich nicht die gesamte Tabellenansicht bei jeder Rotation usw. neu laden wollen)?

Beispiel Unterseite Zelle, wo Schatten korrekt angewendet wird: enter image description here

Bottom of Zelle in derselben tableview nach dem Scrollen nach unten (shadow nur für den ersten 75% der Breite angewendet wird): enter image description here

Edit: ich habe das Problem bemerkt haben aus diesen Zeilen Code verursacht wird:

CGRect shadowFrame = view.layer.bounds; 
CGPathRef shadowPath = [UIBezierPath bezierPathWithRect:shadowFrame].CGPath; 
view.layer.shadowPath = shadowPath; 

Wenn ich le ave ihnen aus, alles ist in Ordnung. Aber mir wurde gesagt, dass es einen bestimmten Leistungsvorteil gibt, wenn man das benutzt. Irgendwie wird der Schatten nach dem Drehen nicht korrekt auf neue Dimensionen angewendet.

+0

Es scheint, dass Sie dies aufrufen, bevor die Grenzen der Zelle auf die richtige Größe festgelegt wurden. Wenn Sie das automatische Layout verwenden, können Sie versuchen, 'layoutSubviews' in Ihrer 'UITableViewCell' -Unterklasse zu überschreiben und sie nach dem Aufruf von' super.layoutSubviews() ' – beyowulf

+0

@beyowulf aufzurufen. Tatsächlich ist es bereits eine Unterklasse von UITableViewCell und diese Methode wird von layoutSubViews aufgerufen . Ich habe es bis zum Anwenden des Schattenpfads verfolgt, siehe Bearbeiten. – edwardmp

Antwort

5

Sie können den Setzer für den Rahmen Ihrer Zelle außer Kraft setzen und anrufen. Sie können diese besser optimieren Ihre Zelle Größe zu speichern und nur den Schattenpfad zu aktualisieren, wenn die Größenänderungen zum Beispiel:

@property (nonatomic, assign) CGSize size; 

Und

- (void) setFrame:(CGRect)frame 
{ 
    [super setFrame:frame]; 
    // Need to check make sure this subview has been initialized 
    if(self.subviewThatNeedsShadow != nil && !CGSizeEqualToSize(self.size,_frame.size) 
    { 
     [self addShadowToView: self.subviewThatNeedsShadow]; 
    } 
} 
+0

Funktioniert super (abgesehen davon, dass _frame = frame [super setFrame: frame] sein muss), danke. Was ich immer noch nicht verstehe ist, warum das funktioniert und das Anwenden des Shadows in 'layoutSubviews' nicht, weil ich diese Methode als Geräte-Rotation mit einem anderen Frame sehe. – edwardmp

+0

Viele Leute denken, dass 'layoutSubviews' direkt analog zu 'viewDidLayoutSubviews' ist (d. H. Dass nach jedem Durchlauf der Layout-Engine aufgerufen wird). Dies ist nicht der Fall. Für eine kurze Beschreibung, wann es aufgerufen wird, siehe [hier] (http://stackoverflow.com/a/9983584/5442445). – beyowulf

1

Die einfachste Lösung ist, die Schatten auf die UITableViewCell ist hinzuzufügen contentView (gegenüber der Ebene für die Hintergrundansicht der Zelle). Da sich die Grenzen der Zelle beim Blättern ändern, , wenn Sie den Schatten zur Stammansicht hinzufügen, müssten Sie den Pfad des Schattens bei jedem Bildlaufereignis aktualisieren, was kostspielig und nicht notwendig wäre.

Sie sind definitiv richtig re: die Performance-Hit durch nicht explizit die shadowPath obwohl. Wenn Sie in der Zelle keinen animierten Inhalt haben, rate ich Ihnen, ihn zu rasterisieren, um die Leistung weiter zu verbessern.

EDIT: Sie müssen auch sicherstellen, dass, wenn Sie den Schattenpfad festlegen, dass die Grenzen der contentView in ihrer "endgültigen" Position sind. Wenn die Größe der Zelle später geändert wird, führt dies dazu, dass sich die Grenzen von contentView ändern und somit ein falscher shadowPath. Die Lösung besteht darin, den Pfad in der UITableViewCell - layoutSubviews Methode zu aktualisieren.

+0

Der Schatten muss zu einer Unteransicht und nicht zur gesamten Zelle (contentView) hinzugefügt werden. Ich habe den Pfad in layoutSubviews jedoch bereits aktualisiert. – edwardmp

0

Hierbei handelt es sich nicht um den übergeordneten Ansichtsrahmen, in dem es sich um den Unterlayer und dessen Größe handelt, die geändert werden sollten, wenn sich das Layout ändert. Sie können die folgende Methode überschreiben, die Ihnen hilft, beim Ändern des Layouts den richtigen Frame einzurichten.

public override void LayoutSublayersOfLayer(CALayer layer) 
{ 

    base.LayoutSublayersOfLayer(layer); 
    if (layer.Name == "gradient") 
    { 
      layer.Frame = view.Layer.Frame; 
    } 
} 

In obigem Code view ist die, wo Sie sublayer hinzugefügt. Wenn Sie mit mehreren Ebenen in derselben Ansicht spielen, können Sie die Eigenschaft name verwenden, um auf einer bestimmten Ebene zu arbeiten.