14

我的应用程序中有一个 UIScrollView,我在其他一些应用程序中看到,当用户滚动时,顶部会在滚动时淡出,而不仅仅是消失。

我真的很喜欢这种效果,并想实现它。有什么想法可以做到吗?

4

6 回答 6

22

简单的 2020 解决方案:

import UIKit

class FadeTail: UIIView {
    
    private lazy var gradientLayer: CAGradientLayer = {
        let l = CAGradientLayer()
        l.startPoint = CGPoint(x: 0.5, y: 0)
        l.endPoint = CGPoint(x: 0.5, y: 1)
        let baseColor = UIColor.white // for example
        l.colors = [
            baseColor.withAlphaComponent(0),
            baseColor.withAlphaComponent(1),
        ].map{$0.cgColor}
        layer.addSublayer(l)
        return l
    }()
    
    override func layoutSubviews() {
        super.layoutSubviews()
        gradientLayer.frame = bounds
    }
}

简单地

  • 在情节提要中自动布局该视图,
  • 你想要的任何形状或大小
  • 在您希望被淡化的视图(文本、图像、网络视图、任何东西)之上。

简单的。

在此处输入图像描述

提示 - 渐变、圆圈等

如果您需要疯狂的圆形/带状/等渐变,请使用此处的技术:https ://stackoverflow.com/a/61174086/294884

在此处输入图像描述

于 2014-08-20T15:33:42.067 回答
13

编辑:我已将此代码放在 github 上,请参见此处


请参阅对类似问题的回答。

我的解决方案是子类UIScrollView化,并在方法中创建一个遮罩层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

上面的代码将顶部和底部UIScrollView从背景颜色淡化为透明,但这可以很容易地更改为仅淡化顶部(或淡化为您想要的任何颜色)。

更改此行以仅淡化顶部:

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

编辑2:

或者仅通过更改这两行来淡化顶部:

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

    gradientLayer.locations = [NSArray arrayWithObjects: [NSNumber numberWithFloat:0],
                                                         [NSNumber numberWithFloat:fadePercentage], nil];

或者,仅淡化底部:

// 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];
于 2013-07-22T00:34:20.497 回答
9

您可以使用CAGradientLayerby

  1. 将 QuartzCore.framework 添加到您的项目中(请参阅链接到库或框架)。

  2. 添加#importQuartzCore 头文件:

    #import <QuartzCore/QuartzCore.h>
    
  3. 然后使用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];
    }
    

请注意,这CAGradientLayer是从 alpha 为 0.0(例如clearColor)的颜色到 alpha 为 1.0 的颜色(例如 )的渐变whiteColor,而不仅仅是从黑色到白色。您可以调整startPoint(默认值可能很好)和endPoint调整要应用渐变的位置。

通常,在使用 a 执行此操作时UIScrollView,除非您希望渐变与您一起滚动,否则您将创建UIScrollView其他的 a 子视图UIView并将此渐变应用于该容器视图,而不是滚动视图本身。

于 2013-07-21T17:55:13.267 回答
5

感谢 Fattie 的回答,我在 Swift 中创建了以下 UIView 扩展,它负责渐变渐变并提供更多样式(底部、顶部、左右、垂直和水平)以及渐变百分比。

对于任何意见/建议,请让我知道我创建的要点,我会尝试通过我添加的任何更改来保持这一点和这个答案是最新的。

扩展:

extension UIView {

    enum UIViewFadeStyle {
        case bottom
        case top
        case left
        case right

        case vertical
        case horizontal
    }

    func fadeView(style: UIViewFadeStyle = .bottom, percentage: Double = 0.07) {
        let gradient = CAGradientLayer()
        gradient.frame = bounds
        gradient.colors = [UIColor.white.cgColor, UIColor.clear.cgColor]

        let startLocation = percentage
        let endLocation = 1 - percentage

        switch style {
        case .bottom:
            gradient.startPoint = CGPoint(x: 0.5, y: endLocation)
            gradient.endPoint = CGPoint(x: 0.5, y: 1)
        case .top:
            gradient.startPoint = CGPoint(x: 0.5, y: startLocation)
            gradient.endPoint = CGPoint(x: 0.5, y: 0.0)
        case .vertical:
            gradient.startPoint = CGPoint(x: 0.5, y: 0.0)
            gradient.endPoint = CGPoint(x: 0.5, y: 1.0)
            gradient.colors = [UIColor.clear.cgColor, UIColor.white.cgColor, UIColor.white.cgColor, UIColor.clear.cgColor]
            gradient.locations = [0.0, startLocation, endLocation, 1.0] as [NSNumber]

        case .left:
            gradient.startPoint = CGPoint(x: startLocation, y: 0.5)
            gradient.endPoint = CGPoint(x: 0.0, y: 0.5)
        case .right:
            gradient.startPoint = CGPoint(x: endLocation, y: 0.5)
            gradient.endPoint = CGPoint(x: 1, y: 0.5)
        case .horizontal:
            gradient.startPoint = CGPoint(x: 0.0, y: 0.5)
            gradient.endPoint = CGPoint(x: 1.0, y: 0.5)
            gradient.colors = [UIColor.clear.cgColor, UIColor.white.cgColor, UIColor.white.cgColor, UIColor.clear.cgColor]
            gradient.locations = [0.0, startLocation, endLocation, 1.0] as [NSNumber]
        }

        layer.mask = gradient
    }

}
于 2018-05-30T11:49:21.943 回答
2

您将 alpha 蒙版层添加到包含滚动视图的视图中,如下所示:

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);

其中“scrollMask”是定义遮罩区域的灰度图像:白色 == 完全遮罩,黑色 == 根本不遮罩,灰色 == 部分遮罩。

要创建您正在寻找的效果,蒙版图像将是黑色的,顶部有一个白色渐变,如下所示:

在此处输入图像描述

有关更多详细信息,请查看CGImageMaskCreate.

于 2013-07-21T17:51:31.687 回答
1

我们在 Steph Sharp 的代码上构建了仅在必要时淡出。我们的代码设置为静态实用程序方法而不是子类,以便我们可以在 UIScrollView 和 UITableView 的子类中重用该方法。这是我们的静态实用程序方法:

#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;
}

这是我们对该方法的使用。

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
于 2015-06-05T18:59:31.477 回答