iOS-带图片的跑马灯,可自定义view

网上有很多跑马灯的demo,但是都是没有带图片的,所以只能自己写一个了

我的思路就是直接用scrollView,上面放view,让他一直滚
(可以把scrollView换成tableView的)

主要用到了setContentOffset这个方法

但是使用


[self.scrollView setContentOffset:CGPointMake(0,0) animated:YES];

返回到最初时却出现了一个bug,就是视图往回滚了

所以我就想要不多写一个视图,让他代替CGPointMake(0,0) 的动画,到时关掉动画效果就行了,说干就干


#import "HorseRaceLampView.h"

#import "UIView+Extionsiton.h"

#import "HorseRaceLampCell.h"

@interface HorseRaceLampView ()<UIScrollViewDelegate>

/**

 定时器

 */

@property (nonatomic, strong) NSTimer *timer;

/**

 滚动视图

 */

@property (nonatomic, strong) UIScrollView *scrollView;

/**

 记录已经加载的视图

 */

@property (nonatomic, strong) NSMutableArray *viewList;

/**

 当前滑动第几个界面 1开始

 */

@property (nonatomic, assign) NSInteger currentIndex;

/**

 处理的数组,因为要避免回退动画,就是最后一个回到第一个

 */

@property (nonatomic, strong) NSMutableArray *tempArr;

@end

@implementationHorseRaceLampView

-(instancetype)initWithFrame:(CGRect)frame{



    if(self= [superinitWithFrame:frame]) {

        [selfinitialize];

        [selfcreateUI];

    }

    return self;

}

#pragma mark - 生命周期

-(void)dealloc{

    [self.timer invalidate];

    self.timer=nil;

}

#pragma mark - 初始化

-(void)initialize{

    self.currentIndex = 1;

}

#pragma mark - 创建UI

-(void)createUI{

    self.scrollView = [[UIScrollView alloc] initWithFrame:self.bounds];

    self.scrollView.backgroundColor = UIColor.grayColor;

    self.scrollView.scrollEnabled = NO;

    self.scrollView.showsVerticalScrollIndicator = NO;

    self.scrollView.showsHorizontalScrollIndicator = NO;

    self.scrollView.delegate = self;

    [self addSubview:self.scrollView];

}

#pragma mark - 私用方法

#pragma mark - 公共方法

- (void)startAnimation {

    if (!self.timer.isValid) {

        [self.timerfire];

    }

}

-(void) stopAnimation{  //结束动画

    if (self.timer.isValid) {

        [self.timer invalidate];

        self.timer=nil;

    }

}

#pragma mark - 通知方法

#pragma mark - 监听代理

-(void)refreshProgress{

    CGFloat y = self.currentIndex * self.scrollView.height;

    self.currentIndex++;

    [self.scrollView setContentOffset:CGPointMake(0,y) animated:YES];

}

#pragma mark - 点击事件

#pragma mark - 代理协议

// 当滚动视图动画完成后,调用该方法,如果没有动画,那么该方法将不被调用

- (void)scrollViewDidEndScrollingAnimation:(UIScrollView*)scrollView{

    if (self.currentIndex == self.tempArr.count) {

        self.currentIndex=1;

        [self.scrollView setContentOffset:CGPointMake(0,0) animated:NO];

    }

}

#pragma mark - 网络请求

#pragma mark - 懒加载

- (NSMutableArray*)viewList{

    if(!_viewList) {

        _viewList = [[NSMutableArray alloc] init];

    }

    return _viewList;

}

-(NSTimer*)timer{

    if(!_timer) {

        _timer = [NSTimer timerWithTimeInterval: 1.0f target:self selector:@selector(refreshProgress) userInfo:nil repeats:YES];

        [[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSRunLoopCommonModes];

    }

    return _timer;

}

-(NSMutableArray *)tempArr{

    if(!_tempArr) {

        _tempArr= [[NSMutableArrayalloc]init];

    }

    return _tempArr;

}

#pragma mark - getset方法

-(void)setModels:(NSArray*)models{

    _models= models;



    //移除动画

    [self.scrollView.layer removeAllAnimations];



    //先移除之前的item

        for(UIView*vinself.scrollView.subviews) {

            if([visKindOfClass:[HorseRaceLampCellclass]]) {

                [vremoveFromSuperview];

            }

        }

        [self.viewList removeAllObjects];





    //    为了解决闪一下,所以要加多加一个view用来替代动画

    self.tempArr = [NSMutableArray arrayWithArray:models];

    // 数据要加第一个

    [self.tempArr addObject:models.firstObject];



    for(inti =0; i

        NSDictionary*dic =self.tempArr[i];



        HorseRaceLampCell *nb = [HorseRaceLampCell initView];

        nb.backgroundColor = [UIColor purpleColor];

        nb.frame = CGRectMake(0, (i*self.scrollView.height), self.scrollView.width, self.scrollView.height);

        nb.tag= i;

        nb.titleLB.text= dic[@"title"];

        nb.iconImgV.image= [UIImageimageNamed:dic[@"icon"]];



        [self.scrollView addSubview:nb];

        [self.viewList addObject:nb];

    }



    self.scrollView.contentSize = CGSizeMake(0, self.tempArr.count * self.scrollView.height);

    self.clipsToBounds = YES;



}


HorseRaceLampView *marqueeView = [[HorseRaceLampView alloc] initWithFrame:CGRectMake(0,100,self.view.bounds.size.width,44)];

    [self.view addSubview:marqueeView];

    [marqueeView setModels:@[@{@"title":@"你好吗",@"icon":@"login-password"},@{@"title":@"我很好",@"icon":@"login-phone"}]];

    //开始动画

    [marqueeView startAnimation];

当然也有很多可以优化的地方
以上就是全部代码了,HorseRaceLampCell这个自定义替换成需求样式就好了

代码是在http://www.cnblogs.com/qqcc1388/p/8664280.html的基础上改的
转载:http://www.cnblogs.com/qqcc1388/p/8664280.html

在分享一个swift版的,也是自定义视图的
用collectionView做的 复制一下代码就可以直接用

import UIKit

enum Roll {
    case ver    /// 垂直
    case hor    /// 水平
}

class HorseRunningLightsView: UIView {

    deinit {
        if timer.isValid {
            timer.invalidate()
        }
    }
    
    /// 定时器
    private lazy var timer : Timer = {
        let timer = Timer(timeInterval: 2.0, target: self, selector: #selector(startToMove), userInfo: nil, repeats: true)
        RunLoop.current.add(timer, forMode: .common)
        return timer
    }()
    
    
    /// 创建布局对象
    let flowLayout = UICollectionViewFlowLayout()
    
    /// collectionView
    private lazy var collectionView : UICollectionView = {
        let collectionView = UICollectionView(frame: self.bounds, collectionViewLayout: flowLayout)
        collectionView.delegate = self
        collectionView.dataSource = self
        collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "cell")
        return collectionView
    }()
    
    /// 滚动方向
    private var rollType : Roll?
    
    /// 当前滑动第几个cell
    private var currentIndex : Int?
    
    /// 处理的数组,因为要避免回退动画,就是最后一个回到第一个
    private var tempList : Array<Any>?
    
    /// 数据源
    var models : Array<Any>? {
        didSet {
            guard models != nil && (models?.count)! > 0 else {
                return
            }
            tempList = Array(models!)
            /// 添加多一个数据源用来作过渡
            tempList?.append(models?.first as Any)
            
            /// 延迟2秒
            timer.fireDate = Date(timeIntervalSinceNow: 2)
        }
    }
    
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        initialize()
        createUI()
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    /// 出现构造方法
    convenience init(frame: CGRect,type: Roll) {
        self.init(frame: frame)
        rollType = type
        if type == Roll.ver {
            flowLayout.scrollDirection = .vertical
        }else{
            flowLayout.scrollDirection = .horizontal
        }
    }
    
    
    
}

extension HorseRunningLightsView: UICollectionViewDelegate,UICollectionViewDataSource {
    
    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return tempList?.count ?? 0
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
        if indexPath.row == 0 {
            cell.backgroundColor = UIColor.red
        }else if indexPath.row == 1 {
            cell.backgroundColor = UIColor.yellow
        }else if indexPath.row == 2 {
            cell.backgroundColor = UIColor.green
        }else if indexPath.row == 3 {
            cell.backgroundColor = UIColor.blue
        }else if indexPath.row == 4 {
            cell.backgroundColor = UIColor.purple
        }
        return cell
    }
}

extension HorseRunningLightsView: UICollectionViewDelegateFlowLayout {
    /// cell尺寸
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(width: self.collectionView.width, height: self.collectionView.height)
    }
    
    /// 这个是两行cell之间的间距(上下行cell的间距)
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
        return 0
    }
    
    /// 定义每个Section的四边间距
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
        return UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
    }
    
}

extension HorseRunningLightsView: UIScrollViewDelegate {
    /// scrollView的动画结束后会进入此方法
    /// 当滚动到最后一个的处理
    func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
        if self.currentIndex == self.tempList?.count {
            self.currentIndex = 1
            self.collectionView.setContentOffset(CGPoint(x: 0, y: 0), animated: false)
        }
    }
}

extension HorseRunningLightsView {
    func initialize() {
        currentIndex = 1
    }
    
    func createUI() {
        addSubview(collectionView)
    }
}

extension HorseRunningLightsView {
    @objc private func startToMove(){
        if rollType == Roll.ver {
            let y = CGFloat(self.currentIndex!) * self.collectionView.height
            self.currentIndex = self.currentIndex! + 1
            self.collectionView.setContentOffset(CGPoint(x: 0, y: y), animated: true)
        }else{
            let x = CGFloat(self.currentIndex!) * self.collectionView.width
            self.currentIndex = self.currentIndex! + 1
            self.collectionView.setContentOffset(CGPoint(x: x, y: 0), animated: true)
        }
    }
}
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        let v = HorseRunningLightsView(frame: CGRect(x: 0, y: 100, width: self.view.width, height: 44), type: Roll.hor)
        v.models = ["你好吗","呵呵呵","你还好意思问我","我这不是在关心你嘛"]
        view.addSubview(v)
    }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,558评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,002评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,024评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,144评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,255评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,295评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,068评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,478评论 1 305
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,789评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,965评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,649评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,267评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,982评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,800评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,847评论 2 351