[实现跑马灯,以及弹幕] -- iOS

HBPmd

设计图.jpg

用法

{

    HBdansView *_randomDansView;
  
}

    _randomDansView = [[HBdansView alloc] initWithFrame:CGRectMake(0, 84, self.view.width, 320)]; //初始化
 
    [self.view addSubview:_randomDansView];

    [_randomDansView addRandomText:@"需要展现的文字"];

需求

  • 上图中有两种方式去展示弹幕
  • 广播式:每次只播放一条数据。
  • 分布式:屏幕中最多显示3条数据

实在想不出其他名字,暂用分布式来表述吧。

思路

分两部分

  • 背景
  • 文字

实现

首先的话,文字是用一个UILable添加到背景UIView上面。但是分布式怎么办?由此设计一个对外属性countInScreen来确定,同时可以在屏幕显示多少个弹幕的内容。

- (void)setCountInScreen:(NSInteger)countInScreen
{
    _countInScreen = countInScreen;
    
    if (self.randomSet.count) [self.randomSet removeAllObjects];
    //    随机
    if (_countInScreen > 10) _countInScreen = 10;
    CGFloat margin = (self.height - _countInScreen * defaultH) / (_countInScreen + 1);
    for (NSInteger i = 0; i < _countInScreen; i++) {
        HBdansLable *randomLable = [HBdansLable dansLableFrame:[self randomFrame]];
        randomLable.y = i * (margin + defaultH) + margin;
        randomLable.delegate = self;
        randomLable.layer.masksToBounds = YES;
        
        [self.randomSet addObject:randomLable];
        
    }
    
}

在代码中,会创建等数目HBdansLable自定义Lable,算出自己的frame。当然,间距是等分的。

randomSet是一个可变的集合。是这样的

- (NSMutableSet *)randomSet
{
    if (!_randomSet) {
        
        _randomSet = [NSMutableSet set];
        
    }
    return _randomSet;
}

搞这个集合的目的是:一开始所有新创建的对象都放这里面去,你可以把这个想象成一个缓存池。用的时候从里面取出HBdansLable对象,展示出来;弹幕滚出父试图,就把此对象回收,重新加到randomSet集合中。

这样你所需的所有HBdansLable对象,在一开始的时候就已经创建好了。后面用的时候,不需要重复创建。

#pragma mark - HBdansLableDelegate
- (void)dansLable:(HBdansLable *)dansLable isOutScreen:(BOOL)isOutScreen
{
   if (isOutScreen) {
       
       dansLable.x = CGRectGetMaxX(self.frame);//更新x值
       
       [dansLable removeFromSuperview];//从父试图中移除
       
       [self.randomSet addObject:dansLable];//添加到集合中国
       
       if (self.randomMutableArray.count){
           
           [self dequeRandomLable:[self.randomMutableArray firstObject]];
           [self.randomMutableArray removeObjectAtIndex:0];
           
       }
   }
}

完成回收HBdansLableDelegate通知;

每个HBdansLable都需要自己去移动,更新frame

- (void)setText:(NSString *)text
{
   [super setText:text];
   //1.更具文字内容算出宽高
   CGRect contextFrame = [text boundingRectWithSize:CGSizeMake(MAXFLOAT, self.height)
                                            options:NSStringDrawingUsesLineFragmentOrigin
                                         attributes:@{NSFontAttributeName : [UIFont systemFontOfSize:17]}
                                            context:nil];
   NSString *str = [NSString stringWithFormat:@"%.f",contextFrame.size.width + 10];
   self.width = [str floatValue];
   self.height = contextFrame.size.height + 6;
   //2.开始弹幕
   [self starDans];
}

重写HBdansLable setter方法,启动弹幕;

- (void)starDans
{
   
   self.displayLink.paused = NO;
   [self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
   self.isStar = YES;
   
}
- (void)stopDans
{
   if (self.displayLink.isPaused) return;
   self.displayLink.paused = YES;
   self.isStar = NO;
   [self.displayLink invalidate];
   self.displayLink = nil;
   
}

一定要加入RunLoop循环中,否则触摸屏幕或者他操作会影响弹幕不再移动。销毁神马的,你们都懂的。

结束总结

就两个注意

  • HBdansLable自己控制移动,算出宽高
  • 父试图控制回收HBdansLable(不需要重复创建);

如果这个文章帮到了你,一定给我Star哦!

GitHub 欢迎围观!!

Tip

  • 本项目仅支持文字弹幕,后续会持续更新。
  • 实现思路仅来源项目需求,所以不是完全适用所有需求场景。

你可能感兴趣的:([实现跑马灯,以及弹幕] -- iOS)