1. 程式人生 > >支援水平 / 垂直顯示自動滾動的跑馬燈控制元件 --- SKAutoScrollLabel 的使用和實現

支援水平 / 垂直顯示自動滾動的跑馬燈控制元件 --- SKAutoScrollLabel 的使用和實現

簡述

SKAutoScrollLabel是一個同時支援水平/垂直兩種型別的“跑馬燈”效果的自動滾動UILabel。在滾動的邊緣使用了梯度褪色來解決滾動邊緣生硬的效果問題,總體效果呈現出混然天成的感覺,並且使用簡單方便。如果你覺得還不錯,請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];

基本設定

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

實現

※ 這裡僅列出關鍵步驟,具體方法請查閱原始碼

  1. 我們需要建立一個數組,來存放我們滾動時所需要展示的label,這裡我們只建立兩個label存放到陣列中即可(滾動只需要兩個即可達成持續跑馬燈的效果)
    // 建立label陣列
     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.區分水平和垂直的UILabel

static void each_object(NSArray *objects, void (^block)(UILabel * label)) {
    for (UILabel * label in objects) {
        block(label);
    }
}
__block float offset = 0;
     // 遍歷label陣列中的元素
    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) {
            // 動態獲取長度和高度, 以此達到將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.判斷滾動條件,是否允許滾動

// (水平方向) 判斷當前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)) {// (垂直方向) 判斷當前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);

        // 調整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一直重複動畫
    [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];
        // 完成後循呼叫
        if (finished) {
            [self performSelector:@selector(scrollLabelIfNeeded)];
        }
    }];

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

        // 建立梯度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);
        }

        // 設定漸變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;

            }
        }

        // 將計算結果交給mask
        gradientMask.locations = @[@0, leftFadePoint, rightFadePoint, @1];

        [CATransaction begin];
        [CATransaction setDisableActions:YES];
        self.layer.mask = gradientMask;
        [CATransaction commit];

感謝你花時間閱讀以上內容, 如果這個專案能夠幫助到你,記得告訴我

Email: [email protected]