一种简洁的文字轮播 DNVerticalTextScrollView

前言:本人小白,写的不好,请大家多多指教。


文字轮播.gif
  1. 新建一个类继承自UIView,在这里名为 DNVerticalTextScrollView
  2. .h 文件中
    1) 代理
// 点击文字轮播的代理
@protocol DNVerticalTextScrollViewDelegate <NSObject>

@optional;
// 使用代理方法回调 Label 点击手势
- (void)dn_textScrollViewSelectedAtIndex:(NSInteger)index content:(NSString *)content;
@end

2) 外部可传入的参数

// 滚动的文字数组
@property (nonatomic,   copy) NSArray *dataArray;
// 文本的颜色
@property (nonatomic, strong) UIColor *textColor;
// DNVerticalTextScrollView 的背景颜色
@property (nonatomic, strong) UIColor *BGColor;
// 字体大小
@property (nonatomic, assign) CGFloat textFontSize;
// 代理
@property (nonatomic, weak) id<DNVerticalTextScrollViewDelegate> delegate;
// 创建方法(可用init或initWithFrame方法,传入数组 dataArray)
- (instancetype)initWithDataArray:(NSArray *)dataArray;    
  1. .m实现文件
    1) 懒加载 UIScrollView
- (UIScrollView *)bgScrollView {
    
    if (!_bgScrollView) {
        _bgScrollView = [[UIScrollView alloc] init];
        _bgScrollView.backgroundColor = UIColor.clearColor;
        // 不显示水平滚动条
        _bgScrollView.showsHorizontalScrollIndicator = NO;
        // 不显示竖直滚动条
        _bgScrollView.showsVerticalScrollIndicator = NO;
        _bgScrollView.scrollEnabled = NO;
        _bgScrollView.pagingEnabled = YES;
        _bgScrollView.bounces = NO;
        _bgScrollView.delegate = self;
        [self addSubview:_bgScrollView];
    }
    return _bgScrollView;
}

2)根据 initWithDataArray 创建方法或者外部传入的 dataArray 得到数据,设置 ScrollView 的 contentSize,创建 Label,并用代理回调 Label 的点击手势事件

// 防止重复添加
    [self.bgScrollView.subviews enumerateObjectsUsingBlock:^(__kindof UIView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        
        [obj removeFromSuperview];
    }];
// 遍历数组,创建 UILabel
    [self.dataArray enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        
        UILabel * label = [self createScrollTextLabelWithTag:idx text:obj];
        [self.bgScrollView addSubview:label];
    }];       
- (UILabel *)createScrollTextLabelWithTag:(NSInteger)tag text:(NSString *)text {
    
    UILabel * label = [[UILabel alloc] init];
    label.text = text;
    label.userInteractionEnabled = YES;
    label.font = [UIFont systemFontOfSize:titleFontSize];
    label.textColor = titleTextColor;
    label.textAlignment = NSTextAlignmentCenter;
    label.frame = CGRectMake(0, tag*self.frame.size.height, self.frame.size.width, self.frame.size.height);
    // 添加点击事件
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(clickTheLabel:)];
    [label addGestureRecognizer:tap];
    tap.view.tag = tag;
    
    return label;
}

// 手势的响应事件
- (void)clickTheLabel:(UITapGestureRecognizer *)gesture {
    // 使用代理方法回调 Label 的点击事件
    if (self.delegate && [self.delegate respondsToSelector:@selector(dn_textScrollViewSelectedAtIndex:content:)]) {
        
        [self.delegate dn_textScrollViewSelectedAtIndex:gesture.view.tag
                                                   content:self.dataArray[gesture.view.tag]];
    }
} 

至此界面搭建基本完成,然后添加定时器,让文字滚动起来

#pragma mark - - - NSTimer
- (void)addTimer {
    
    /*
     scheduledTimerWithTimeInterval:  滑动视图的时候timer会停止
     这个方法会默认把Timer以NSDefaultRunLoopMode添加到主Runloop上,而当你滑tableView的时候,就不是NSDefaultRunLoopMode了,这样,你的timer就会停了。
     */
    [self removeTimer];
    self.timer = [NSTimer timerWithTimeInterval:3
                                         target:self
                                       selector:@selector(nextLabel)
                                       userInfo:nil
                                        repeats:YES];
    [[NSRunLoop mainRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
}

// 定时器的响应事件
- (void)nextLabel {
    
    CGPoint oldPoint = self.bgScrollView.contentOffset;
    oldPoint.y += self.bgScrollView.frame.size.height;
    [self.bgScrollView setContentOffset:oldPoint animated:YES];
}
- (void)removeTimer {
    [_timer invalidate];
    _timer = nil;
}

当 scrollView 的contentoffset 滚动到设置的 contentSize 的位置是就没法向下滚动了,所以这时我们再代理中将 contentOffset 设置为起始的 contentOffset

#pragma mark -- UIScrollView Delegate

//当滚动时调用scrollView的代理方法
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    // 当滚动到最底部时,返回(0,0)
    CGFloat currentOffset = self.bgScrollView.frame.size.height*(self.dataArray.count);
    if (self.bgScrollView.contentOffset.y == currentOffset) {
        [self.bgScrollView setContentOffset:CGPointMake(0, 0) animated:NO];
    }
}

这样一个文字轮播基本就完成了,但是当我们的 scrollView 滚动的时候,定时器还是在运作的,所以我们应当在 scrollView 的代理方法中设置定时器的开启或移除

// 开始拖拽的时候调用
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
    
    [self removeTimer];
}

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
    //开启定时器
    [self addTimer];
}

最后,在 dealloc 中移除定时器

- (void)dealloc {
    [_timer invalidate];
    _timer = nil;
}

demo地址DNVerticalTextScrollView

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1、通过CocoaPods安装项目名称项目信息 AFNetworking网络请求组件 FMDB本地数据库组件 SD...
    阳明AI阅读 16,023评论 3 119
  • python的send2trash模块,顾名思义就是把一个文件丢入回收站。
  • 室友说,你考不上的,那个证那么那么难。可是,我还是想考,室友的万般阻挠下,我终于崩溃了。忍不住的给妈妈打了电话,记...
    嘉善1996阅读 173评论 0 2
  • 很多遇见总是沧海一粟般地在风霜雨雪之后,美丽而又苍茫地笼罩长河的上空,温柔着漫漫人生路。 春雨和风云是以原告和法官...
    雪心雨心阅读 210评论 0 1