iOS - 支持水平/垂直顯示自動滾動的跑馬燈控件 --- SKAutoScrollLabel的使用和實現(xiàn)

簡述

SKAutoScrollLabel是一個同時支持水平/垂直兩種類型的“跑馬燈”效果的自動滾動UILabel。在滾動的邊緣使用了梯度褪色來解決滾動邊緣生硬的效果問題,總體效果呈現(xiàn)出混然天成的感覺,并且使用簡單方便。如果你覺得還不錯,請star支持一下吧~


效果圖

如何開始

1.從GitHub上Clone-->SKAutoScrollLabel,然后查看Demo

2.直接將目錄下的SKAutoScrollLabel拷貝到工程中,或在podfile文件夾中添加 pod 'SKAutoScrollLabel'

使用方法

初始化

SKAutoScrollLabel * leftLabel = [[SKAutoScrollLabel alloc] initWithFrame:CGRectMake(50, 50, [UIScreen mainScreen].bounds.size.width - 100, 50)];
[self.view addSubview:leftLabel];

基本設(shè)置

leftLabel.backgroundColor = [UIColor blackColor];// 背景色
leftLabel.textColor = [UIColor whiteColor];// 字體顏色
leftLabel.font = [UIFont systemFontOfSize:16];// 字體大小
leftLabel.direction = SK_AUTOSCROLL_DIRECTION_LEFT;// 滾動方向,這是向左滾動
leftLabel.text = text;// 顯示內(nèi)容

實現(xiàn)

※ 這里僅列出關(guān)鍵步驟,具體方法請查閱源碼

  1. 我們需要創(chuàng)建一個數(shù)組,來存放我們滾動時所需要展示的label,這里我們只創(chuàng)建兩個label存放到數(shù)組中即可(滾動只需要兩個即可達(dá)成持續(xù)跑馬燈的效果)
// 創(chuàng)建label數(shù)組
    NSMutableSet * labelSet = [[NSMutableSet alloc] init];
    for (NSInteger i = 0; i < kLabelCount; i++) {
        UILabel * label = [UILabel new];
        label.backgroundColor = [UIColor clearColor];
        label.autoresizingMask = self.autoresizingMask;
        label.frame = CGRectMake(0, 0, 50, 50);
        [self.scrollView addSubview:label];
        [labelSet addObject:label];
    }
    self.labels = [labelSet.allObjects copy];

2.區(qū)分水平和垂直的UILabel

static void each_object(NSArray *objects, void (^block)(UILabel * label)) {
    for (UILabel * label in objects) {
        block(label);
    }
}

__block float offset = 0;
     // 遍歷label數(shù)組中的元素
    each_object(self.labels, ^(UILabel *label) {
        [label sizeToFit];
        
        CGRect frame = label.frame;
        // 垂直
        if (self.direction != SK_AUTOSCROLL_DIRECTION_RIGHT && self.direction != SK_AUTOSCROLL_DIRECTION_LEFT) {
            // 動態(tài)獲取長度和高度, 以此達(dá)到將label垂直的目的
            NSDictionary * attribute = [NSDictionary dictionaryWithObjectsAndKeys:self.font,NSFontAttributeName, nil];
            CGSize sizeWord = [@"一" boundingRectWithSize:self.bounds.size options:NSStringDrawingUsesFontLeading | NSStringDrawingUsesLineFragmentOrigin attributes:attribute context:nil].size;
            CGFloat wordWidth = sizeWord.width;
            CGSize sizeStr = [self.text boundingRectWithSize:CGSizeMake(wordWidth, CGFLOAT_MAX) options:NSStringDrawingUsesFontLeading | NSStringDrawingUsesLineFragmentOrigin attributes:attribute context:nil].size;
            CGFloat wordHeight = sizeStr.height;
            
            frame.origin = CGPointMake((CGRectGetWidth(self.frame) / 2) - (wordWidth / 2), offset);
            frame.size = CGSizeMake(wordWidth, wordHeight);
            label.frame = frame;
            label.numberOfLines = 0;
            offset += CGRectGetHeight(label.bounds) + self.labelSpacing;
            
        } else {// 水平
            frame.origin = CGPointMake(offset, 0);
            frame.size.height = CGRectGetHeight(self.bounds);
            label.frame = frame;
            offset += CGRectGetWidth(label.bounds) + self.labelSpacing;
            // 重新定位label在scrollview中的位置
            label.center = CGPointMake(label.center.x, roundf(self.center.y - CGRectGetMinY(self.frame)));
        }
        
    });

3.判斷滾動條件,是否允許滾動

// (水平方向) 判斷當(dāng)前scrollLabel是否大于self的寬度,如果是就開始滾動
    if (CGRectGetWidth(self.scrollLabel.bounds) > CGRectGetWidth(self.bounds)) {
        CGSize size = CGSizeMake(CGRectGetWidth(self.scrollLabel.bounds) + CGRectGetWidth(self.bounds) + self.labelSpacing,  CGRectGetHeight(self.bounds));
        self.scrollView.contentSize = size;
        
        EACH_LABEL(hidden, NO);
        
        [self applyGradientMaskForFadeLength:kDefaultFadeLength enableFade:self.scrolling];
        [self scrollLabelIfNeeded];
        
    } else if (CGRectGetHeight(self.scrollLabel.bounds) > CGRectGetHeight(self.bounds)) {// (垂直方向) 判斷當(dāng)前scrollLabel是否大于self的高度,如果是就開始滾動
        CGSize size = CGSizeMake(CGRectGetWidth(self.bounds), CGRectGetHeight(self.scrollLabel.bounds) + self.labelSpacing);
        self.scrollView.contentSize = size;
        
        EACH_LABEL(hidden, NO);
        
        [self applyGradientMaskForFadeLength:kDefaultFadeLength enableFade:self.scrolling];
        [self scrollLabelIfNeeded];
        
    } else {
        // 隱藏其他label
        EACH_LABEL(hidden, self.scrollLabel != label);
        
        // 調(diào)整scrollView和scrollLabel
        self.scrollView.contentSize = self.bounds.size;
        self.scrollLabel.frame = self.bounds;
        self.scrollLabel.hidden = NO;
        self.scrollLabel.textAlignment = NSTextAlignmentCenter;
        
        [self.scrollView.layer removeAllAnimations];
        
        [self applyGradientMaskForFadeLength:0 enableFade:NO];
    }

4.自動滾動動畫

switch (self.direction) {// 滾動方向
        case SK_AUTOSCROLL_DIRECTION_LEFT:
            self.scrollView.contentOffset = CGPointZero;
            break;
        case SK_AUTOSCROLL_DIRECTION_RIGHT:
            self.scrollView.contentOffset = CGPointMake(width + self.labelSpacing, 0);
            break;
        case SK_AUTOSCROLL_DIRECTION_TOP:
            self.scrollView.contentOffset = CGPointZero;
            break;
        case SK_AUTOSCROLL_DIRECTION_BOTTOM:
            self.scrollView.contentOffset = CGPointMake(0, height - 10 - CGRectGetHeight(self.bounds));
            break;
    }
        
    // 滾動動畫, UIViewAnimationOptionRepeat一直重復(fù)動畫
    [UIView animateWithDuration:duration delay:self.autoScrollInterval options:UIViewAnimationOptionRepeat animations:^{

        switch (self.direction) {
            case SK_AUTOSCROLL_DIRECTION_LEFT:
                self.scrollView.contentOffset = CGPointMake(width + self.labelSpacing, 0);
                break;
            case SK_AUTOSCROLL_DIRECTION_RIGHT:
                self.scrollView.contentOffset = CGPointZero;
                break;
            case SK_AUTOSCROLL_DIRECTION_TOP:
                self.scrollView.contentOffset = CGPointMake(0, CGRectGetHeight(self.scrollLabel.bounds) + self.labelSpacing);
                break;
            case SK_AUTOSCROLL_DIRECTION_BOTTOM:
                self.scrollView.contentOffset = CGPointZero;

                break;
        }

    } completion:^(BOOL finished) {
        _scrolling = NO;
        // 移除陰影
        [self applyGradientMaskForFadeLength:kDefaultFadeLength enableFade:NO];
        // 完成后循調(diào)用
        if (finished) {
            [self performSelector:@selector(scrollLabelIfNeeded)];
        }
    }];

5.使用CAGradientLayer在滾動邊緣的制造梯度褪色效果

        // 創(chuàng)建梯度mask和消失長度
        CAGradientLayer * gradientMask = [CAGradientLayer layer];
        gradientMask.bounds = self.layer.bounds;
        gradientMask.position = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));
        
        gradientMask.shouldRasterize = YES;
        gradientMask.rasterizationScale = [UIScreen mainScreen].scale;
        
        CGFloat fadePoint = 0;
        // 垂直方向的梯度褪色
        if (self.direction != SK_AUTOSCROLL_DIRECTION_RIGHT && self.direction != SK_AUTOSCROLL_DIRECTION_LEFT) {
            gradientMask.startPoint = CGPointMake(CGRectGetMidX(self.frame), 0);
            gradientMask.endPoint = CGPointMake(CGRectGetMidX(self.frame), 1);
            fadePoint = fadeLength / CGRectGetHeight(self.bounds);
        // 水平方向的梯度褪色
        } else {
            gradientMask.startPoint = CGPointMake(0, CGRectGetMidY(self.frame));
            gradientMask.endPoint = CGPointMake(1, CGRectGetMidY(self.frame));
            fadePoint = fadeLength / CGRectGetWidth(self.bounds);
        }
        
        // 設(shè)置漸變mask顏色和位置
        id transparent = (id)[UIColor clearColor].CGColor;
        id opaque = (id)[UIColor blackColor].CGColor;
        gradientMask.colors = @[transparent, opaque, opaque, transparent];
        
        // 計算褪色
        NSNumber * leftFadePoint = @(fadePoint);
        NSNumber * rightFadePoint = @(1 - fadePoint);
        if (!fade) {
            switch (self.direction) {
                case SK_AUTOSCROLL_DIRECTION_LEFT:
                    leftFadePoint = @0;
                    break;
                case SK_AUTOSCROLL_DIRECTION_RIGHT:
                    leftFadePoint = @0;
                    rightFadePoint = @1;
                    break;
                case SK_AUTOSCROLL_DIRECTION_TOP:
                    leftFadePoint = @0;
                    break;
                case SK_AUTOSCROLL_DIRECTION_BOTTOM:
                    leftFadePoint = @0;
                    rightFadePoint = @1;
                    break;

            }
        }
        
        // 將計算結(jié)果交給mask
        gradientMask.locations = @[@0, leftFadePoint, rightFadePoint, @1];
        
        [CATransaction begin];
        [CATransaction setDisableActions:YES];
        self.layer.mask = gradientMask;
        [CATransaction commit];

感謝你花時間閱讀以上內(nèi)容, 如果這個項目能夠幫助到你,記得告訴我

Email: shevakuilin@gmail.com

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容