首先看下效果图
水平文字轮播
实现原理
将一个文字数组传给该组件,
该组件先判断文字是否足够长,在足够长的情况下
添加轮播功能。
轮播功能的实现,为了达到无限轮播效果,创建了三组同样的文案,
我们默认展示的是中间的那一组,当滚动到最后那一第一条的时候,马上返回到中间那一组的第一条,这样就达到了无缝衔接的效果
逻辑可用下面的图简单理解
当滚动到第三组的时候,迅速切换到第二组,
达到无缝衔接的效果
核心代码
#pragma mark - 展示数据
- (void)loadWithContentArray:(NSArray <NSString *> *)contentArray
{
if ([contentArray isEqualToArray:_contentArray]) {
return;
}
if (self.superview && CGSizeEqualToSize(self.scrollview.bounds.size, CGSizeZero)) {
//初始化没有设置scrollviewFrame 的时候需要更新 scrollview的frame
[self.superview layoutIfNeeded];
self.scrollview.frame = CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height);
}
_contentArray = contentArray;
NSMutableArray *marray = [NSMutableArray array];
//为达到循环轮播的效果添加三个相同数组
[marray addObjectsFromArray:contentArray];
[marray addObjectsFromArray:contentArray];
[marray addObjectsFromArray:contentArray];
[self.scrollview.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
[self showContentWithArray:marray.copy];
}
- (void)showContentWithArray:(NSArray *)array
{
CGFloat x = 0;
NSInteger i = 0;
for (NSString *string in array)
{
CGFloat width = [string boundingRectWithSize:CGSizeMake(100000, 16) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName: self.font} context:nil].size.width + 40;
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setTitle:string forState:UIControlStateNormal];
button.titleLabel.font = self.font;
button.titleEdgeInsets = UIEdgeInsetsMake(button.titleEdgeInsets.top, 0, button.titleEdgeInsets.bottom, button.titleEdgeInsets.right + button.titleEdgeInsets.left);
[button setTitleColor:self.textColor forState:UIControlStateNormal];
button.frame = CGRectMake(x, 0, width, self.bounds.size.height);
button.tag = 300 + i;
[button addTarget:self action:@selector(click:) forControlEvents:UIControlEventTouchUpInside];
[self.scrollview addSubview:button];
x += width;
if (i == array.count/3 - 1) {
/// array.cont/3 -1 时最后一条文案的索引序号
//如果所有的消息加到一起都没有scrollview宽度长,则不轮播
if (CGRectGetMaxX(button.frame) < self.scrollview.bounds.size.width) {
[self stopScroll];
self.hasLinker = NO;
break;
}
}
if (i == array.count - 1) {
self.scrollview.contentSize = CGSizeMake(CGRectGetMaxX(button.frame), self.bounds.size.height);
[self.scrollview setContentOffset:CGPointZero animated:NO];
}
if (i == array.count - 1) {
if (!_linker) {
[self startScroll];
}
}
i++;
}
}
达到临界偏移量的时候,迅速修改偏移量
#pragma mark - scrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if (scrollView.contentOffset.x > scrollView.contentSize.width/3.0 * 2) {
[self.scrollview setContentOffset:CGPointMake(scrollView.contentSize.width/3.0 + (scrollView.contentOffset.x - scrollView.contentSize.width/3.0 * 2), 0) animated:NO];
}
}
另外,我这里使用CADisplayLink 实现计时器
```objectivec
self.linker = [CADisplayLink lb_displayLinkWithTarget:self selector:@selector(displayLinkAction)];
[self.linker addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
self.hasLinker = YES;
使用方法
pod ‘LBHorizontalTextLoopView’
- (LBHorizontalTextLoopView *)textLoopView
{
if (!_textLoopView) {
_textLoopView = [[LBHorizontalTextLoopView alloc] initWithFrame:CGRectMake(10, 100, 350, 40)];
_textLoopView.backgroundColor = [UIColor cyanColor];
_textLoopView.delegate = self;
_textLoopView.textColor = [UIColor redColor];
_textLoopView.font = [UIFont systemFontOfSize:18];
}
return _textLoopView;
}
#展示文案数组
[self.textLoopView loadWithContentArray:@[@"预计今年底通车,上海金山最后一条未通车省际道路已完成八成"]];
#点击事件
#pragma mark - LBHorizontalTextLoopViewDelegate
- (void)horizontalLoopViewdidSelectItemAtIndex:(NSInteger)index
{
NSLog(@"点击点击点击点击%ld",(long)index);
}
demo
如果对您有用,欢迎star