前言:本人小白,写的不好,请大家多多指教。
- 新建一个类继承自UIView,在这里名为 DNVerticalTextScrollView
- .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;
- .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