¿Cómo crear un efecto de desvanecimiento superior usando UIScrollView?

Tengo una UIScrollView en mi aplicación y he visto en otras aplicaciones que cuando el usuario se desplaza, la sección superior se desvanece en desplazamiento en lugar de desaparecer.

Realmente amo este efecto y quiero lograrlo. ¿Alguna idea de cómo se puede hacer?

EDIT: He puesto este código en github, ver aquí .


Mira mi respuesta a una pregunta similar.

Mi solución es subclass UIScrollView y crear una capa de máscara en el método layoutSubviews .

 #import "FadingScrollView.h" #import <QuartzCore/QuartzCore.h> static float const fadePercentage = 0.2; @implementation FadingScrollView // ... - (void)layoutSubviews { [super layoutSubviews]; NSObject * transparent = (NSObject *) [[UIColor colorWithWhite:0 alpha:0] CGColor]; NSObject * opaque = (NSObject *) [[UIColor colorWithWhite:0 alpha:1] CGColor]; CALayer * maskLayer = [CALayer layer]; maskLayer.frame = self.bounds; CAGradientLayer * gradientLayer = [CAGradientLayer layer]; gradientLayer.frame = CGRectMake(self.bounds.origin.x, 0, self.bounds.size.width, self.bounds.size.height); gradientLayer.colors = [NSArray arrayWithObjects: transparent, opaque, opaque, transparent, nil]; // Set percentage of scrollview that fades at top & bottom gradientLayer.locations = [NSArray arrayWithObjects: [NSNumber numberWithFloat:0], [NSNumber numberWithFloat:fadePercentage], [NSNumber numberWithFloat:1.0 - fadePercentage], [NSNumber numberWithFloat:1], nil]; [maskLayer addSublayer:gradientLayer]; self.layer.mask = maskLayer; } @end 

El código anterior desvanece la parte superior e inferior de UIScrollView del color de background a transparente, pero esto se puede cambiar fácilmente para desvanecer solo la parte superior (o desvanecerse en cualquier color que desee).

Cambie esta línea para desvanecer solo la parte superior:

 // Fade top of scrollview only gradientLayer.locations = [NSArray arrayWithObjects: [NSNumber numberWithFloat:0], [NSNumber numberWithFloat:fadePercentage], [NSNumber numberWithFloat:1], [NSNumber numberWithFloat:1], nil]; 

EDIT 2:

O desvanezca la parte superior solo cambiando estas dos líneas:

 // Fade top of scrollview only gradientLayer.colors = [NSArray arrayWithObjects: transparent, opaque, nil]; gradientLayer.locations = [NSArray arrayWithObjects: [NSNumber numberWithFloat:0], [NSNumber numberWithFloat:fadePercentage], nil]; 

O desvanecer solo el background:

 // Fade bottom of scrollview only gradientLayer.colors = [NSArray arrayWithObjects: opaque, transparent, nil]; gradientLayer.locations = [NSArray arrayWithObjects: [NSNumber numberWithFloat:1.0 - fadePercentage], [NSNumber numberWithFloat:1], nil]; 

Puede usar un CAGradientLayer de

  1. Agregando QuartzCore.framework a su proyecto (consulte Vincular a la biblioteca o Framework ).

  2. Agregue #import de los encabezados de QuartzCore:

     #import <QuartzCore/QuartzCore.h> 
  3. Y luego use CAGradientLayer :

     - (void)addGradientMaskToView:(UIView *)view { CAGradientLayer *gradient = [CAGradientLayer layer]; gradient.frame = view.bounds; gradient.colors = @[(id)[[UIColor clearColor] CGColor], (id)[[UIColor whiteColor] CGColor]]; gradient.startPoint = CGPointMake(0.5, 0.0); // this is the default value, so this line is not needed gradient.endPoint = CGPointMake(0.5, 0.20); [view.layer setMask:gradient]; } 

Tenga en count que este CAGradientLayer es un gradiente de un color con un alfa de 0.0 (por ejemplo, clearColor ) a un color con un alfa de 1.0 (por ejemplo, whiteColor ), no solo de negro a blanco. Puede ajustar el punto startPoint (el valor pnetworkingeterminado probablemente sea endPoint ) y el punto endPoint para ajustar donde desea que se aplique el gradiente.

Y, en general, al hacer esto con un UIScrollView , a less que desee que el degradado se desplace con usted, convierta UIScrollView una subvista de otra UIView y aplique este degradado a esa vista de contenedor, no a la vista de desplazamiento.

Simplemente basado en la gran respuesta de Rob, aquí hay una categoría en UIView,

 @implementation UIView (Looks) -(void)fadeTail { CAGradientLayer *gradient = [CAGradientLayer layer]; gradient.frame = self.bounds; gradient.colors = @[ (id)[[UIColor whiteColor] CGColor], (id)[[UIColor clearColor] CGColor] ]; gradient.startPoint = CGPointMake(0.5, 0.93); gradient.endPoint = CGPointMake(0.5, 1); [self.layer setMask:gradient]; } @end 

que hace esto … visto aquí en un pequeño UIWebView …

introduzca la descripción de la imagen aquí

(Para ser claros, la vista web en sí misma es blanca , la vista web está sentada sobre un background grisáceo . Por lo tanto, la function fadeTail básicamente desvanece la vista web "completa", a lo que ocurra debajo).

Espero que salve a alguien un poco escribiendo, saludos

Agregue una capa de máscara alfa a una vista que contiene su vista de desplazamiento como esta:

 CALayer *mask = [CALayer layer]; CGImageRef maskRef = [UIImage imageNamed:@"scrollMask"].CGImage; CGImageRef maskImage = CGImageMaskCreate(CGImageGetWidth(maskRef), CGImageGetHeight(maskRef), CGImageGetBitsPerComponent(maskRef), CGImageGetBitsPerPixel(maskRef), CGImageGetBytesPerRow(maskRef), CGImageGetDataProvider(maskRef), NULL, false); mask.contents = (__bridge id)maskImage; mask.frame = CGRectMake(0, 0, view.bounds.size.width, view.bounds.size.height); view.layer.mask = mask; view.layer.masksToBounds = YES; CGImageRelease(maskImage); 

donde "scrollMask" es una image en escala de grises que define la región de la máscara: blanco == completamente enmascarado, negro == sin enmascarar en absoluto y gris == parcialmente enmascarado.

Para crear el efecto que está buscando, la image de la máscara sería negra con un degradado blanco en la parte superior así:

introduzca la descripción de la imagen aquí

Para get más detalles, consulte la documentation de CGImageMaskCreate .

Nos basamos en el código de Steph Sharp para que solo se desvanezca cuando sea necesario. Nuestro código se configura como un método de utilidad estático en lugar de una subclass para que podamos reutilizar el método en nuestras subclasss de UIScrollView y UITableView. Aquí está nuestro método de utilidad estática:

 #define kScrollViewFadeColorLight [UIColor colorWithRed:0.56 green:0.56 blue:0.56 alpha:0.0] #define kScrollViewFadeColorDark [UIColor colorWithRed:0.56 green:0.56 blue:0.56 alpha:1.0] #define kScrollViewScrollBarWidth 7.0 #define kScrollViewFadingEdgeLength 40.0 + (void) applyFadeToScrollView:(UIScrollView*) scrollView { CGFloat topOffset = -scrollView.contentInset.top; CGFloat bottomOffset = scrollView.contentSize.height + scrollView.contentInset.bottom - scrollView.bounds.size.height; CGFloat distanceFromTop = scrollView.contentOffset.y - topOffset; CGFloat distanceFromBottom = bottomOffset - scrollView.contentOffset.y; BOOL isAtTop = distanceFromTop < 1.0; BOOL isAtBottom = distanceFromBottom < 1.0; if (isAtTop && isAtBottom) { // There is no scrolling to be done here, so don't fade anything! scrollView.layer.mask = nil; return; } NSObject* transparent = (NSObject*)[kScrollViewFadeColorLight CGColor]; NSObject* opaque = (NSObject*)[kScrollViewFadeColorDark CGColor]; CALayer* maskLayer = [CALayer layer]; maskLayer.frame = scrollView.bounds; CALayer* scrollGutterLayer = [CALayer layer]; scrollGutterLayer.frame = CGRectMake(scrollView.bounds.size.width - kScrollViewScrollBarWidth, 0.0, kScrollViewScrollBarWidth, scrollView.bounds.size.height); scrollGutterLayer.backgroundColor = (__bridge CGColorRef)(opaque); [maskLayer addSublayer:scrollGutterLayer]; CAGradientLayer* gradientLayer = [CAGradientLayer layer]; gradientLayer.frame = CGRectMake(0.0, 0.0, scrollView.bounds.size.width, scrollView.bounds.size.height); CGFloat fadePercentage = kScrollViewFadingEdgeLength / scrollView.bounds.size.height; NSMutableArray* colors = [[NSMutableArray alloc] init]; NSMutableArray* locations = [[NSMutableArray alloc] init]; if (!isAtTop) { [colors addObjectsFromArray:@[transparent, opaque]]; [locations addObjectsFromArray:@[@0.0, [NSNumber numberWithFloat:fadePercentage]]]; } if (!isAtBottom) { [colors addObjectsFromArray:@[opaque, transparent]]; [locations addObjectsFromArray:@[[NSNumber numberWithFloat:1.0 - fadePercentage], @1.0]]; } gradientLayer.colors = colors; gradientLayer.locations = locations; [maskLayer addSublayer:gradientLayer]; scrollView.layer.mask = maskLayer; } 

Aquí está nuestro uso de ese método.

FadingScrollView.h

 @interface FadingScrollView : UIScrollView @end 

FadingScrollView.m

 @implementation FadingScrollView - (void) layoutSubviews { [super layoutSubviews]; [Utils applyFadeToScrollView:self]; } @end 

FadingTableView.h

 @interface FadingTableView : UITableView @end 

FadingTableView.m

 @implementation FadingTableView - (void) layoutSubviews { [super layoutSubviews]; [Utils applyFadeToScrollView:self]; } @end 

Las vistas son todas subvistas de la vista de desplazamiento para que cada una tenga su propio alpha . Puede actuar como delegado para la vista de desplazamiento y en scrollViewDidScroll puede verificar el contentOffset la contentOffset y cambiar el valor alpha de cualquiera de las subvistas que desee.