Как создать эффект верхнего затухания с помощью UIScrollView?
У меня есть UIScrollView в моем приложении, и я видел в некоторых других приложениях, которые, когда пользователь прокручивается, верхняя часть исчезает на свитке, а не просто исчезает.
Мне очень нравится этот эффект и я хочу его достичь. Любые идеи, как это можно сделать?
Ответы
Ответ 1
Просто основанный на большом ответе Роб, здесь категория на 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
который делает это.. рассматривается здесь на небольшом UIWebView...
![enter image description here]()
(Чтобы быть ясным, сам веб-представление белый, веб-представление, похоже, сидит на фоне серого цвета. Таким образом, функция fadeTail в основном угасает "весь" веб-просмотр, что бы ни случилось внизу.)
Надеюсь, что это поможет кому-то немного набирать текст, приветствия
Ответ 2
РЕДАКТИРОВАТЬ: Я поставил этот код на 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];
Ответ 3
Вы можете использовать CAGradientLayer
на
-
Добавление в проект проекта QuartzCore.framework(см. Связь с библиотекой или Framework).
-
Добавьте #import
заголовков QuartzCore:
#import <QuartzCore/QuartzCore.h>
-
И затем используйте 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
является градиентом от цвета с альфой 0.0 (например, clearColor
) до цвета к цвету с альфой 1.0 (например, whiteColor
), а не только от черного до белого. Вы можете настроить startPoint
(значение по умолчанию, вероятно, хорошо) и endPoint
, чтобы настроить, где вы хотите применить градиент.
И вообще, когда вы делаете это с помощью UIScrollView
, если вы не хотите, чтобы градиент прокручивался вместе с вами, вы делаете UIScrollView
подвью другого UIView
и применяете этот градиент к этому представлению контейнера, а не к просмотр прокрутки.
Ответ 4
Благодаря ответу Fattie я создал следующее расширение UIView в Swift, которое заботится о затухании градиента и предоставляет больше стилей (снизу, сверху, слева направо, по вертикали и горизонтали), а также процент затухания.
Если у вас есть какие-либо комментарии или рекомендации, сообщите мне об этом в сущности, которую я создал. Я стараюсь обновлять и этот, и этот ответ с учетом всех внесенных изменений.
Расширение:
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
}
}
Ответ 5
Вы добавляете альфа-маску к виду, содержащему ваше прокрутку, например:
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" - это оттенок серого, определяющий область маски: белый == полностью замаскированный, черный == не замаскирован вообще и серый == частично замаскирован.
Чтобы создать эффект, который вы ищете, изображение маски будет черным с белым градиентом вверху, как это:
![enter image description here]()
Подробнее см. документацию для CGImageMaskCreate
.
Ответ 6
Мы построили код 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
Ответ 7
Представления - все вложенные представления прокрутки, поэтому каждый из них имеет свой собственный alpha
. Вы можете выступать в качестве делегата для просмотра прокрутки, а в scrollViewDidScroll
вы можете проверить contentOffset
и изменить alpha
любого из ваших подсмотров.