UIScrollView 周围的 Safari 风格渐变阴影

Posted

技术标签:

【中文标题】UIScrollView 周围的 Safari 风格渐变阴影【英文标题】:Safari-style gradient shadows around UIScrollView 【发布时间】:2011-03-24 17:04:25 【问题描述】:

我一直希望通过在内容周围添加某种阴影来美化 UIScrollView,当视图大于内容时可见。 Safari 使用页面周围的灰色渐变来做到这一点(捏以使网页更小并平移以查看边缘的渐变)

有很多关于类似主题的讨论,但他们似乎都在讨论 UITableView(内容上方和下方的渐变)的解决方案,而不是需要围绕所有四个边缘渐变的 UIScrollView。

我最初使用了图层效果(见下文),但这明显影响了性能,并且平移和缩放变得不稳定,尤其是在使用 Retina 显示屏时,所以我将其删除。

ChartView *chartView = [[ChartView alloc] initWithChild:child type:type];
// Give it a nice shadow -- Unfortunately this kills performance, especially on Retina phones
aChartView.layer.masksToBounds = NO;
aChartView.layer.shadowOffset = CGSizeMake(10, 12);
aChartView.layer.shadowRadius = 20;
aChartView.layer.shadowOpacity = 0.6;
// Create the scroll view (root view)
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:frame];
scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;   // Allow automatic resizing in orientation changes
scrollView.backgroundColor = [UIColor lightGrayColor];
scrollView.delegate = self;
[scrollView addSubview:chartView];

我尝试继承 UIScrollView 并覆盖 drawRect 并且能够绘制背景,但它只被调用一次,因此我无法在内容移动/调整大小时调整背景。

Safari 不使用阴影,而是使用某种渐变(顺便提一下,如果你仔细观察的话,它的边角看起来有些不完美),也许这会提供更好的性能。有人知道他们是怎么做到的吗?

编辑

这个问题现在已经解决了,我已经把我的实现(UIScrollView 的一个子类,它添加了 Safari 风格的渐变阴影)放在 GitHub 上,供正在寻找相同东西的读者使用:https://github.com/Clafou/ShadowedScrollView

【问题讨论】:

【参考方案1】:

我认为你是对的,角落是问题所在。我知道使用 layer.cornerRadius 确实会降低性能,我认为 shadowRadius 可能也会这样做。

可能更好的选择是像 Safari 那样做,即在所有四个面上添加一个 CAGradientLayer。使用 Safari,他们在视图后面开始渐变,这样角落仍然会被着色,但它的副作用是让它们看起来有点奇怪。但是,这可能是图形密集度最低的方式。

查找 CAGradientLayer 的示例非常容易。默认为垂直渐变。要使其成为水平渐变,只需设置起点和终点:

gradient.startPoint = CGPointMake(0, 0.5);
gradient.endPoint = CGPointMake(1.0, 0.5);

【讨论】:

太棒了!我已经开始在从完全透明到不透明的所有四个侧面上尝试使用 CAGradientLayers,实际上,通过正确的渐变组合,角落似乎确实可以令人满意地融合,与 Safari 角落中看到的类似缺陷。覆盖 layoutSubviews 允许在用户移动/缩放视图时重新定位它们,因此无需覆盖 drawRect。我还有一些实现细节要完成,但您已经找到了解决方案,非常感谢! 很难让一切都正确(尤其是当 UIScrollView 进行动画缩放时,当捏合手势以弹跳结束时动画阴影),但我现在已经做到了! :) 谢谢【参考方案2】:

对于性能问题有一个更简单的答案 - 只需设置一个与视图轮廓匹配的阴影路径:

    aChartView.layer.shadowPath = [UIBezierPath bezierPathWithRect:aChartView.bounds].CGPath;

【讨论】:

谢谢,我不知道这个属性,听起来很棒! 没问题。一段时间前,我遇到了这个性能问题,使用阴影,设置 shadowPath 就像魔术一样。我的猜测是,如果没有设置阴影路径,每次绘制视图时,它都必须动态“跟踪”视图的轮廓以确定阴影路径,从而导致巨大的性能损失。

以上是关于UIScrollView 周围的 Safari 风格渐变阴影的主要内容,如果未能解决你的问题,请参考以下文章

chrome/safari 显示图像周围的边框

css 删除输入周围的边框(Chrome,Safari)

如何在 div 或 iframe 等其他元素上模拟活动输入或 textarea 周围的 Chrome/Safari 边框?

UIScrollView里面的UIWebView上面的UIToolbar

在 Safari/Mail 等中模拟 iOS 缩放工具

UIScrollview 不允许我滚动整个图像