iOS自定义垂直滚动轮播视图

最近因为项目需求,需要用到类似淘宝,天猫,京东的文字垂直轮播效果,网上找了不少类似demo之后,决定自己动手造一个,为了增加可扩展性,把滚动的子视图全部交给使用者来处理,先看下效果图
advertScroll.gif

调用示例代码如下:

_labelView = [[LFAdvertScrollView alloc] initWithFrame:CGRectMake(0, 100, ScreenWidth, 40)];
_labelView.totalCount = 4;
_labelView.dataSource = self;
_labelView.delegate = self;
[self.view addSubview:_labelView];

_attbriuteView = [[LFAdvertScrollView alloc] initWithFrame:CGRectMake(0, 160, ScreenWidth, 60)];
_attbriuteView.totalCount = 4;
_attbriuteView.dataSource = self;
_attbriuteView.delegate = self;
[self.view addSubview:_attbriuteView];

_imageView = [[LFAdvertScrollView alloc] initWithFrame:CGRectMake(0, 240, ScreenWidth, 200)];
_imageView.totalCount = 4;
_imageView.dataSource = self;
_imageView.delegate = self;
[self.view addSubview:_imageView];

遵循代理要实现的方法:

   - (Class)customViewClassForAdvertScrollView:(LFAdvertScrollView *)view {
    if (view == _labelView) {
        return [UILabel class];
    } else if (view == _imageView) {
        return [UIImageView class];
    } else {
        return [CustomAdvertView class];
    }
}
- (void)configCustomView:(UIView *)view forIndex:(NSInteger)index advertView:(nonnull LFAdvertScrollView *)advertView {
    if (advertView == _labelView) {
        UILabel *testLabel = (UILabel *)view;
        testLabel.text = @[@"I'm Li Bai",@"I'm Du Fu",@"I'm Bai Ju Yi",@"I'm Wang An Shi"][index];
        testLabel.textAlignment = NSTextAlignmentCenter;
        testLabel.textColor = [UIColor purpleColor];
        testLabel.font = [UIFont boldSystemFontOfSize:16];
        testLabel.backgroundColor = [UIColor cyanColor];
    } else if (advertView == _imageView) {
        UIImageView *imageView = (UIImageView *)view;
        imageView.image = [UIImage imageNamed:@[@"h1.jpg",
                                                @"h2.jpg",
                                                @"h3.jpg",
                                                @"h4.jpg"][index]];
        
    } else {
        CustomAdvertView *customView = (CustomAdvertView *)view;
        customView.leftImage.image = [UIImage imageNamed:@[@"h1.jpg",
                                                           @"h2.jpg",
                                                           @"h3.jpg",
                                                           @"h4.jpg"][index]];
        customView.rightLabel.text = @[@"I'm Li Bai,I'm Li Bai,I'm Li Bai,I'm Li Bai,I'm Li Bai",@"I'm Du Fu",@"I'm Bai Ju Yi",@"I'm Wang An Shi"][index];
    }
 
   
}

重点来了,看了很多都是基于UICollectionView实现的,自动滚动模式下,会返回很多个Item,我这里尝试用UIScrollview复用三个view来实现自动滚动,核心思路是用户看到的永远是中间的那个view,通过控制偏移量来实现自动滚动效果。
LFAdvertScrollView.h文件内容:

@class LFAdvertScrollView;

@protocol LFAdvertScrollViewDataSource <NSObject>


/**
 返回要滚动的视图类型

 @param view LFAdvertScrollView
 @return  返回要滚动的视图类型,!!!:必须是继承于UIView实现的类

 */
- (Class)customViewClassForAdvertScrollView:(LFAdvertScrollView *)view;

@end


@protocol LFAdvertScrollViewDelegate <NSObject>

/**
 给自定义视图赋值

 @param view 赋值的视图
 @param index 第几个视图
 @param advertView LFAdvertScrollView
 */
- (void)configCustomView:(UIView *)view forIndex:(NSInteger)index advertView:(LFAdvertScrollView *)advertView;

/**
 点击回调

 @param advertView LFAdvertScrollView
 @param index 第几个视图
 */
- (void)advertView:(LFAdvertScrollView *)advertView didSelectViewIndex:(NSInteger )index;

@end

@interface LFAdvertScrollView : UIView

/**
 数据源个数,必传项
 */
@property (nonatomic, assign) NSInteger totalCount;

/**
 滚动时间间隔
 */
@property (nonatomic, assign) NSTimeInterval autoScrollInterval;

@property (nonatomic, weak)   id<LFAdvertScrollViewDelegate>delegate;

@property (nonatomic, weak)   id<LFAdvertScrollViewDataSource>dataSource;

@end

实现方式很简单,就是复用三个view实现无限轮播,点击事件只添加到中间的view上面,然后点击回调出当前页码
这是主要实现部分:

///设置事件代理
- (void)setDelegate:(id<LFAdvertScrollViewDelegate>)delegate {
    _delegate = delegate;
    if ([_delegate respondsToSelector:@selector(configCustomView:forIndex:advertView:)]) {
        [self.delegate configCustomView:self.topView forIndex:self.totalCount - 1 advertView:self];
        [self.delegate configCustomView:self.middleView forIndex:0 advertView:self];
        [self.delegate configCustomView:self.bottomView forIndex:1 advertView:self];
    }
}
///设置视图类型代理
- (void)setDataSource:(id<LFAdvertScrollViewDataSource>)dataSource {
    _dataSource = dataSource;
    if (self.dataSource && [self.dataSource respondsToSelector:@selector(customViewClassForAdvertScrollView:)]) {
        ///拿到用户自定义的视图类名
        Class CustomClass = [self.dataSource customViewClassForAdvertScrollView:self];
        
        self.topView = [[CustomClass alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
        
        self.middleView = [[CustomClass alloc] initWithFrame:CGRectMake(0, self.frame.size.height * 1, self.frame.size.width, self.frame.size.height)];
        
        ///用户看到的只有中间视图,所以为了简单起见,只需要添加中间视图的点击响应
        UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(customViewTap)];
        [self.middleView addGestureRecognizer:tap];
        
        self.bottomView = [[CustomClass alloc] initWithFrame:CGRectMake(0, self.frame.size.height * 2, self.frame.size.width, self.frame.size.height)];
        
        [self.contentView addSubview:self.topView];
        [self.contentView addSubview:self.middleView];
        [self.contentView addSubview:self.bottomView];
    }
}

#pragma mark - timer执行的方法
- (void)automaticScroll
{
    self.currentPage++;
    if (self.currentPage  == self.totalCount) {
        self.currentPage = 0;
    }
    [UIView animateWithDuration:1 animations:^{
        ///动画发生的滑动
        self.middleView.userInteractionEnabled =NO;
        self.contentView.contentOffset =CGPointMake(0, CGRectGetHeight(self.contentView.frame) * 2);
    } completion:^(BOOL finished) {
        ///滑动完成后,把当前现实的imageview重现移动回中间位置,此处不能使用动画,用户感觉不到
        ///移动前,先把中间imageview的image设置成当前现实的iamge
        self.middleView.userInteractionEnabled = YES;
        if (self.delegate && [self.delegate respondsToSelector:@selector(configCustomView:forIndex:advertView:)]) {
            [self.delegate configCustomView:self.topView forIndex:self.currentPage == 0 ?self.totalCount - 1 : self.currentPage - 1 advertView:self];
            [self.delegate configCustomView:self.middleView forIndex:self.currentPage advertView:self];
            [self.delegate configCustomView:self.bottomView forIndex:self.currentPage == self.totalCount - 1 ? 0 : self.currentPage + 1 advertView:self];
        }
        self.contentView.contentOffset =CGPointMake(0, CGRectGetHeight(self.contentView.frame) * 1);
    }];

}

#pragma mark - 用户点击

-(void)customViewTap{
    if (self.delegate && [self.delegate respondsToSelector:@selector(advertView:didSelectViewIndex:)]) {
        [self.delegate advertView:self didSelectViewIndex:self.currentPage];
    }
}

代码基本就这些了, 写这篇纯属算是个人笔记,不喜勿喷,有更好的想法或者意见的欢迎大家指出。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,019评论 4 62
  • 今晚,看见音乐,听见舞蹈。惊喜于音乐舞蹈全新的演绎方式外,紧抓我心弦的,是同一个故事,看到不同版本的我们自己,投射...
    房顶一弯弦月阅读 385评论 0 0
  • 生日快乐 对我来说有点特别滴小于。 今天终于做出点东西了 我加油了 棒。现在是八点二十九刚走出工厂 遇上晚自修放学...
    福進進阅读 86评论 0 0
  • 昨天早睡了,今天补上。 昨天我拉着一张茶桌,和明泽一起返程。因为后座没地方坐,不得已坐在了副驾驶位置。可巧,走到界...
    观心不语阅读 148评论 0 0