Iphone UIScrollView上的高性能、可变长度衰减边缘
我试图在Iphone UIScrollView上的高性能、可变长度衰减边缘,iphone,objective-c,ios,core-animation,core-graphics,Iphone,Objective C,Ios,Core Animation,Core Graphics,我试图在UIScrollView上生成一些淡入淡出的边缘,这些边缘具有相当复杂的层次结构,长度可以在滚动时轻松调整。这基本上就是我想要达到的效果(注意淡入淡出的边缘): 棘手的部分是: 背景是动态的 我希望淡出的边缘随着用户的滚动而“增长”;也就是说,当不进行滚动时,它们不存在,但一旦滚动开始,淡入淡出效果会随着contentOffset的增加而增加 与第2条类似,一旦滚动完成,淡入淡出的边缘应平滑收缩 我已经使用自定义的CAGradientLayer获得了我想要的大部分内容,该层用作视图层的
UIScrollView
上生成一些淡入淡出的边缘,这些边缘具有相当复杂的层次结构,长度可以在滚动时轻松调整。这基本上就是我想要达到的效果(注意淡入淡出的边缘):
棘手的部分是:
contentOffset
的增加而增加CAGradientLayer
获得了我想要的大部分内容,该层用作视图层的mask
,但问题是它的性能不够。然后我尝试按需切换掩码,即当滚动开始时,设置掩码,当滚动停止时,移除掩码。这种方法是有效的(有一些bug),但根据苹果公司的文档,我后来发现动态更改掩码有未定义的行为。我还没有确定一个基于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];
}
当与myUIScrollView
一起使用时,我基本上只需调整层的位置以匹配contentOffset
,然后在没有动画的情况下使用setGradientStartLength:endLength:animated:
调整大小(动画不会使速度减慢很多)
正如我所说的,这将实现我想要的功能,但不会达到我所需要的性能水平(帧速率从60fps下降到30帧左右,并将其用作滚动视图的掩码
)。如果不使用mask
属性,我还没有找到一个好的方法来实现这一点,我假设这就是我必须要做的
我的猜测是,使用与上面类似的代码可以实现这一点,但是使用我的层作为子层,而不是视图的掩码
。但是我还没有决定当这个层被用作子层时如何添加这样的淡入淡出效果,我也没有看到任何其他人做过同样的例子
有人能给我指一下正确的方向吗?我发现苹果关于这些东西的文档非常有限。你能发布一张你想要达到的效果的图片吗?可能会提出一些建议。当然。我添加了一张图片和一个更好的效果描述。你能发布一张你想要达到的效果的图片吗?可能会提出一些建议。当然。我添加了一个图像和更好的效果描述。