2010-12-16 3 views
1

Je sous-classe UIScrollView et j'ajoute quelques éléments visuels. En haut, il devrait y avoir un dégradé allant du noir au clair, et au fond il y a un masque qui disparaît vers le bas. J'ai ajouté ces calques et je regarde bien, mais quand je défile, ils restent aux coordonnées que je leur ai données (par rapport à la vue de défilement), plutôt que d'être "fixés" en bas et en haut de la vue. Cette vue de défilement défile uniquement verticalement.Correction de CALayer en haut et en bas de UIScrollView

Voici le code pour 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 

Je connais une solution pour le haut pourrait être simplement d'ajouter une vue séparée contenant un dégradé, mais pour le fond, je crois que je dois utiliser un masque pour le faire faire ce que je veux (fondu en arrière-plan tout en bas). L'arrière-plan est une image, donc je ne peux pas simplement passer au blanc ou à une autre couleur, il faut que ça disparaisse pour effacer. J'ai cherché une méthode qui est appelée quand la vue de défilement est déplacée et l'utilise pour changer la position du masque, mais je n'ai encore rien trouvé. Aucune suggestion?

Répondre

0

Vous pouvez probablement accomplir cela en remplaçant -layoutSubviews sur le UIScrollView, qui est invoqué lorsque ses limites changent.

Une autre technique que je l'ai vu sur les vues comme celle-ci est qu'au lieu de faire cette gestion de la couche de la vue, la sous-classe CALayer, utilisez votre sous-classe comme la couche de vue de défilement, puis dans -layoutSublayers de votre couche, faire pour le même travail quand il se déplace. Je mentionne cette dernière technique, car il semble un peu plus naturel que la couche gère ses sous-couches par rapport à la vue qui gère directement ses sous-couches.

+0

Ah, layoutSubviews était la méthode que je cherchais. Merci! – Ned