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 


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

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

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

@end


@protocol LFAdvertScrollViewDelegate 

/**
 给自定义视图赋值

 @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)   iddelegate;

@property (nonatomic, weak)   iddataSource;

@end

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

///设置事件代理
- (void)setDelegate:(id)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)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];
    }
}

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

你可能感兴趣的:(iOS自定义垂直滚动轮播视图)