2

我试图在UIScrollView具有相当复杂的层次结构的 a 上产生一些褪色边缘,其长度可以在滚动时轻松调整。这基本上是我想要达到的效果(注意褪色边缘):

在此处输入图像描述

棘手的部分是:

  1. 背景是动态的
  2. 我希望褪色边缘随着用户滚动而“增长”;也就是说,当没有滚动时它们不存在,但是一旦滚动开始,淡入淡出效果会随着增加而contentOffset增加
  3. 类似于没有。2、滚动完成后,淡入淡出的边缘应该平滑收缩

我已经CAGradientLayer使用用作mask视图层的自定义来获得我想要的大部分内容,但问题是它在性能方面还不够。然后我尝试按需切换面具,即。当滚动开始时,掩码被设置,当滚动停止时,掩码被移除。根据Apple文档,这种工作(有一些错误),但我后来发现动态更改掩码具有未定义的行为。我还没有确定一个基于 CoreGraphics 的解决方案,我不确定它是否可行或者性能是否会更好。我也不能使用图像来模拟渐变,因为内容和背景都是动态的。

这是CAGradientLayer我创建的自定义子类的实现:

- (id) init {
    self = [super init];
    if (self) {
        self.anchorPoint = CGPointZero;

        self.startPoint = CGPointMake(0.0, 0.5);
        self.endPoint = CGPointMake(1.0, 0.5);

        CGColorRef transluscentColor = [UIColor colorWithWhite:1.0 alpha:0.0].CGColor;
        CGColorRef opaqueColor = [UIColor colorWithWhite:1.0 alpha:1.0].CGColor;

        self.colors = [NSArray arrayWithObjects:
                       (id)opaqueColor,
                       (id)transluscentColor, 
                       (id)opaqueColor, 
                       (id)opaqueColor,
                       (id)transluscentColor,
                       (id)opaqueColor, nil];
        self.locations = [NSArray arrayWithObjects:
                          [NSNumber numberWithFloat:0.0f],
                          [NSNumber numberWithFloat:0.0f],
                          [NSNumber numberWithFloat:0.0f],
                          [NSNumber numberWithFloat:1.0f],
                          [NSNumber numberWithFloat:1.0f],
                          [NSNumber numberWithFloat:1.0f], nil];
    }

    return self;
}

- (void) setAbsoluteStartPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint {
    [CATransaction begin];
    [CATransaction setDisableActions:YES];
    self.startPoint = CGPointMake(startPoint.x / self.bounds.size.width, startPoint.y / self.bounds.size.height);
    self.endPoint = CGPointMake(endPoint.x / self.bounds.size.width, endPoint.y / self.bounds.size.height);
    [CATransaction commit];
}

- (void) setGradientStartLength:(CGFloat)startLength endLength:(CGFloat)endLength animated:(BOOL)animated {
    CGFloat deltaX = (self.endPoint.x - self.startPoint.x);
    CGFloat deltaY = (self.endPoint.y - self.startPoint.y);

    // use the side whose change is largest as our base length
    CGFloat sideLength = (deltaX > deltaY ? self.bounds.size.width * deltaX : self.bounds.size.height * deltaY);

    CGFloat startRatio = MAX((startLength / sideLength), 0.0f);
    CGFloat endRatio = 1.0f - MAX((endLength / sideLength), 0.0f);

    NSArray *locations = [NSArray arrayWithObjects:
                          [NSNumber numberWithFloat:0.0f],
                          [NSNumber numberWithFloat:0.0f],
                          [NSNumber numberWithFloat:startRatio],
                          [NSNumber numberWithFloat:endRatio],
                          [NSNumber numberWithFloat:1.0f],
                          [NSNumber numberWithFloat:1.0f], nil];

    [CATransaction begin];
    if (animated) {
        [CATransaction setAnimationDuration:0.5];
        [CATransaction setAnimationTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]];
    }
    else {
        [CATransaction setDisableActions:YES];
    }

    self.locations = locations;
    [CATransaction commit];
}

当与 my 一起使用时UIScrollView,我基本上只是调整图层position以匹配contentOffset,然后在setGradientStartLength:endLength:animated:不使用动画的情况下调整大小(虽然动画不会减慢速度)。

就像我说的,这会做我想要的,但不是我需要的性能水平(帧率从 60fps 下降到 30 左右,它用作滚动视图mask)。而且我还没有想出一个不使用该mask属性的好方法,我认为这是我必须这样做的方式。

我的猜测是,这可以使用与上面类似的代码来实现,但使用我的层作为子层而不是视图的mask. 但是我还没有确定当图层用作子图层时如何添加这样的淡入淡出效果,而且我还没有看到任何其他人这样做的例子。

谁能在这里指出我正确的方向?我发现 Apple 关于这些事情的文档非常有限。

4

0 回答 0