2010-12-16 13 views
1

Ich Unterklasse UIScrollView und einige visuelle Elemente hinzufügen. An der Spitze sollte ein Farbverlauf von schwarz nach klar sein, und unten ist eine Maske, die nach unten ausläuft. Ich habe diese Ebenen hinzugefügt und sehe richtig aus, aber wenn ich scrolle, bleiben sie an den Koordinaten, in die ich sie eingefügt habe (in Bezug auf die Bildlaufansicht), anstatt am unteren und oberen Rand der Ansicht "fixiert" zu sein. Diese Bildlaufansicht scrollt nur vertikal. HierFixing CALayer oben und unten von UIScrollView

ist der Code für SettingsScrollView.m:

#import "SettingsScrollView.h" 
#import <QuartzCore/QuartzCore.h> 

#define SHADOW_HEIGHT 20.0 
#define SHADOW_INVERSE_HEIGHT 10.0 
#define SHADOW_RATIO (SHADOW_INVERSE_HEIGHT/SHADOW_HEIGHT) 

@implementation SettingsScrollView 


- (id)initWithCoder:(NSCoder *)aDecoder 
{ 
    self = [super initWithCoder:aDecoder]; 

    [self setUpShadow]; 

    return self; 
} 

- (CAGradientLayer *)shadowAsInverse:(BOOL)inverse 
{ 
    CAGradientLayer *newShadow = [[[CAGradientLayer alloc] init] autorelease]; 
    CGRect newShadowFrame = CGRectMake(0, 0, self.frame.size.width, inverse ? SHADOW_INVERSE_HEIGHT : SHADOW_HEIGHT); 
    newShadow.frame = newShadowFrame; 
    CGColorRef darkColor =[UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:inverse ? (SHADOW_INVERSE_HEIGHT/SHADOW_HEIGHT) * 0.5 : 0.5].CGColor; 
    CGColorRef lightColor = [self.backgroundColor colorWithAlphaComponent:0.0].CGColor; 

    newShadow.colors = [NSArray arrayWithObjects: (id)(inverse ? lightColor : darkColor), (id)(inverse ? darkColor : lightColor), nil]; 
    return newShadow; 
} 

- (CAGradientLayer *)gradientMask 
{ 
    CAGradientLayer *mask = [[[CAGradientLayer alloc] init] autorelease]; 
    CGRect maskFrame = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height); 
    mask.frame = maskFrame; 
    CGColorRef darkColor =[UIColor clearColor].CGColor; 
    CGColorRef lightColor =[UIColor blackColor].CGColor; 

    mask.colors = [NSArray arrayWithObjects: (id)lightColor, (id)lightColor, (id)darkColor, nil]; 
    mask.locations = [NSArray arrayWithObjects:[NSNumber numberWithFloat:0.0], [NSNumber numberWithFloat:0.9], [NSNumber numberWithFloat:1.0], nil]; 
    return mask; 
} 

- (void)setUpShadow 
{ 
    CAGradientLayer *topShadowLayer = [self shadowAsInverse:NO]; 
    CAGradientLayer *bottomShadowLayer = [self gradientMask]; 

    [self.layer insertSublayer:topShadowLayer atIndex:0]; 

    [self.layer setMask:bottomShadowLayer]; 

    [CATransaction begin]; 
    [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions]; 

    CGRect topShadowLayerFrame = topShadowLayer.frame; 
    topShadowLayerFrame.size.width = self.frame.size.width; 
    topShadowLayerFrame.origin.y = 0; 
    topShadowLayer.frame = topShadowLayerFrame; 

    CGRect bottomShadowLayerFrame = bottomShadowLayer.frame; 
    bottomShadowLayerFrame.size.width = self.frame.size.width; 
    bottomShadowLayerFrame.origin.y = self.frame.size.height - bottomShadowLayer.frame.size.height; 
    bottomShadowLayer.frame = bottomShadowLayerFrame; 

    [CATransaction commit]; 
} 

@end 

Ich kenne eine Lösung für die oben nur eine separate Ansicht hinzufügen könnte, die einen Gradienten enthält, aber für den Boden Ich glaube, ich brauche zu verwenden eine Maske, damit es macht, was ich will (ganz unten in den Hintergrund einblenden). Der Hintergrund ist ein Bild, so dass ich nicht einfach zu weiß oder einer anderen Farbe verblassen kann, es muss zum Löschen verschwinden. Ich habe nach einer Methode gesucht, die aufgerufen wird, wenn die Bildlaufansicht verschoben wird und damit die Position der Maske ändert, aber ich habe noch nichts gefunden. Irgendwelche Vorschläge?

Antwort

0

Sie könnten dies wahrscheinlich erreichen, indem Sie -layoutSubviews in der UIScrollView überschreiben, die aufgerufen wird, wenn sich die Grenzen ändern.

Eine andere Technik, die ich auf Ansichten wie dies gesehen haben, dass stattdessen aus der Sicht dieser Schicht-Management zu tun, Unterklasse CALayer, Unterklasse als die Ebene des Scroll-Ansicht verwenden, und dann in der Schicht des -layoutSublayers, auf die gleiche Arbeit tun wenn es sich bewegt. Ich erwähne diese letztere Technik, weil es für die Ebene etwas natürlicher erscheint, ihre Unterschichten zu verwalten als die Ansicht, die ihre Ebenen-Unterschichten direkt verwaltet.

+0

Ah, layoutSubviews war die Methode, die ich suchte. Vielen Dank! – Ned