为你的文本框添加进度提示模糊层

2,346 阅读2分钟
原文链接: www.jianshu.com
前言

最近用小黄车发现地图界面下方的渐变模糊效果不错,遂想尝试实现一下。目的为TextView添加渐变模糊层以便提示用户阅读进度。效果如下:


效果图


对于渐变模糊效果我们要通过CAGradientLayer类进行实现。推荐一篇文章CAGradientLayer的一些属性解析书写的比较详细。

该效果结构为主体TextView加上侧与下侧的渐变模糊层,并在TextView滚动时候调节渐变层显隐性即可。

首先分别创建TextView与渐变层

@property (nonatomic, strong) UITextView *textView;
@property (nonatomic, strong) CAGradientLayer *topGradientLayer;
@property (nonatomic, strong) CAGradientLayer *bottomGradientLayer;
- (instancetype)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        [self createTextView];
        [self createGradientLayer];
    }
    return self;
}
- (void)createTextView {
    _textView = [[UITextView alloc]initWithFrame:CGRectZero];
    _textView.delegate = self;
    [self addSubview:_textView];
}
- (void)createGradientLayer {
    //颜色分布
    NSArray *layerColors = @[(__bridge id)RGB(255, 255, 255, 0.0).CGColor, (__bridge id)RGB(255, 255, 255, 0.5).CGColor, (__bridge id)RGB(255, 255, 255, 0.95).CGColor];
    //分割位置
    NSArray *layerLocations = @[@(0.2), @(0.8), @(1.0)];

    _topGradientLayer = [CAGradientLayer layer];
    _topGradientLayer.borderWidth = 0;
    _topGradientLayer.frame = CGRectZero;
    _topGradientLayer.colors = layerColors;
    _topGradientLayer.locations  = layerLocations;
    //自下而上
    _topGradientLayer.startPoint = CGPointMake(0.5, 1.0);
    _topGradientLayer.endPoint = CGPointMake(0.5, 0.0);
    [self.layer addSublayer:_topGradientLayer];

    _bottomGradientLayer = [CAGradientLayer layer];
    _bottomGradientLayer.borderWidth = 0;
    _bottomGradientLayer.frame = CGRectZero;
    _bottomGradientLayer.colors = layerColors;
    _bottomGradientLayer.locations  = layerLocations;
     //自上而下
    _bottomGradientLayer.startPoint = CGPointMake(0.5, 0.0);
    _bottomGradientLayer.endPoint = CGPointMake(0.5, 1.0);
    [self.layer addSublayer:_bottomGradientLayer];

    _topGradientLayer.hidden = YES;
    _bottomGradientLayer.hidden = YES;
}

这里简单讲述下CAGradientLayer的一些重要属性
colors:颜色分布,可将所需颜色存入数组中
locations:颜色间隔位置
startPoint:开始点
endPoint:结束点
需要注意的是Layer的坐标系与通常坐标系有所不同,见下图


Layer坐标系

因此比如startPoint为(0,0)endPoint为(1,0),颜色渐变即为由左向右的方向,以此类推。

接下来在layoutSubviews方法中设置控件坐标并判断当前TextView文字占比是否高于当前TextView本身高度,若高于说明有未显示文字则显示下侧渐变层。这里简单调节了TextView的行间距,需要注意的是TextView设置行间距后系统会给文字上下各加2px。

- (void)layoutSubviews {
    [super layoutSubviews];
    CGFloat width = self.bounds.size.width;
    CGFloat height = self.bounds.size.height;
    _textView.frame = self.bounds;
    _topGradientLayer.frame = CGRectMake(0, 0, width, height / 2);
    _bottomGradientLayer.frame = CGRectMake(0, height / 2, width, height / 2);
    NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
    [paragraphStyle setLineSpacing:6];
    CGSize size = [_textView.text boundingRectWithSize:CGSizeMake(width, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:_textView.font,NSParagraphStyleAttributeName:paragraphStyle} context:NULL].size;
    if (size.height > height) {
        _topGradientLayer.hidden = YES;
        _bottomGradientLayer.hidden = NO;
    }
}

最后因为TextView继承于UIScrollView,所以我们可以在scrollViewDidScroll代理方法中调整上侧下侧渐变层的显隐性以达到我们想要的效果。

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    if (scrollView.contentOffset.y > 15) {
        _topGradientLayer.hidden = NO;
    }else{
        _topGradientLayer.hidden = YES;
    }
    if (scrollView.contentOffset.y < scrollView.contentSize.height - 15 - scrollView.frame.size.height) {
        _bottomGradientLayer.hidden = NO;
    }else{
        _bottomGradientLayer.hidden = YES;
    }
}

这里简单的判断偏移量大于15隐藏上侧显示下侧,偏移量距底部15显示下侧隐藏上侧。

效果实现到此结束,功能比较简单,娱乐一下。。。
demo下载地址