浅析SDCycleScrollView实现原理

来源:互联网 发布:qq 微信 知乎 编辑:程序博客网 时间:2024/05/23 00:04

SDCycleScrollView是使用UICollectionView实现的轮播,图片的网络获取是依赖SDWebImage,也就是说使用SDCycleScrollView你就必须的使用SDWebImage。下面来简单介绍一下SDCycleScrollView的实现原理;

1.SDCycleScrollView的大部分逻辑代码的实现都是放在“SDCycleScrollView.m”文件中,着这个文件里面提供了几个类方法用来初始化。

/** 初始轮播图(推荐使用) */+ (instancetype)cycleScrollViewWithFrame:(CGRect)frame delegate:(id<SDCycleScrollViewDelegate>)delegate placeholderImage:(UIImage *)placeholderImage;+ (instancetype)cycleScrollViewWithFrame:(CGRect)frame imageURLStringsGroup:(NSArray *)imageURLStringsGroup;/** 本地图片轮播初始化方式 */+ (instancetype)cycleScrollViewWithFrame:(CGRect)frame imageNamesGroup:(NSArray *)imageNamesGroup;/** 本地图片轮播初始化方式2,infiniteLoop:是否无限循环 */+ (instancetype)cycleScrollViewWithFrame:(CGRect)frame shouldInfiniteLoop:(BOOL)infiniteLoop imageNamesGroup:(NSArray *)imageNamesGroup;

基本的使用方法

    SDCycleScrollView *cycleScrollView = [SDCycleScrollView cycleScrollViewWithFrame:CGRectMake(0, 64, w, 180) shouldInfiniteLoop:YES imageNamesGroup:imageNames];    cycleScrollView.delegate = self;    cycleScrollView.pageControlStyle = SDCycleScrollViewPageContolStyleAnimated;    [demoContainerView addSubview:cycleScrollView];    cycleScrollView.scrollDirection = UICollectionViewScrollDirectionVertical;

2.在创建方法中实现initWithFrame中实现属性的初始化、设置默认值,同时创建collectionView,在这里他自定义了一个UICollectionCell(SDCollectionViewCell),在这个cell里面添加imageView、label、font等属性。

@interface SDCollectionViewCell : UICollectionViewCell@property (weak, nonatomic) UIImageView *imageView;@property (copy, nonatomic) NSString *title;@property (nonatomic, strong) UIColor *titleLabelTextColor;@property (nonatomic, strong) UIFont *titleLabelTextFont;@property (nonatomic, strong) UIColor *titleLabelBackgroundColor;@property (nonatomic, assign) CGFloat titleLabelHeight;@property (nonatomic, assign) NSTextAlignment titleLabelTextAlignment;@property (nonatomic, assign) BOOL hasConfigured;/** 只展示文字轮播 */@property (nonatomic, assign) BOOL onlyDisplayText;@end

3.这里是实现的全部。在这里也是通过timer来自动轮播的,这里是timer的代码,创建并开启他的runloop,防止滑动的时候卡顿

- (void)setupTimer{    [self invalidateTimer]; // 创建定时器前先停止定时器,不然会出现僵尸定时器,导致轮播频率错误    NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:self.autoScrollTimeInterval target:self selector:@selector(automaticScroll) userInfo:nil repeats:YES];    _timer = timer;    [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];}

计时器执行的方法里面的主要方法就是获取当前的currentIndex,以及滚动到当前的index,我们着重看一下滚动到当前的index这个方法的实现,这里他是做了一个判断,当前的index >= count的时候,就直接滚动到_totalItemsCount *0.5的位置,在这里作者使用这样一句代码

_totalItemsCount = self.infiniteLoop ? self.imagePathsGroup.count * 100 : self.imagePathsGroup.count;

然后作者创建了count * 100的这样的一个collectionView,每次都是从中间位置开始轮播。当currentIndex >= _totalItemsCount的时候就会将contentOffset设置到_totalItemsCount *0.5的位置

- (void)scrollToIndex:(int)targetIndex{    if (targetIndex >= _totalItemsCount) {        if (self.infiniteLoop) {            targetIndex = _totalItemsCount * 0.5;            [_mainView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:targetIndex inSection:0] atScrollPosition:UICollectionViewScrollPositionNone animated:NO];        }        return;    }    [_mainView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:targetIndex inSection:0] atScrollPosition:UICollectionViewScrollPositionNone animated:YES];}

在layoutSubViews方法中作者也实现了类似的方法,初始化的时候就从_totalItemsCount *0.5的位置开始轮播

  if (_mainView.contentOffset.x == 0 &&  _totalItemsCount) {        int targetIndex = 0;        if (self.infiniteLoop) {            targetIndex = _totalItemsCount * 0.5;        }else{            targetIndex = 0;        }        [_mainView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:targetIndex inSection:0] atScrollPosition:UICollectionViewScrollPositionNone animated:NO];    }

这样就达到了轮播的效果。其中有几个值得注意的就是这样写的轮播基本上都会出现将app置于后台一会后再置于前台,有可能会出现卡住的现象。作者在这里添加了一个解决方法:重新设置_totalItemsCount *0.5的位置开始轮播

- (void)adjustWhenControllerViewWillAppera{    long targetIndex = [self currentIndex];    if (targetIndex < _totalItemsCount) {        [_mainView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:targetIndex inSection:0] atScrollPosition:UICollectionViewScrollPositionNone animated:NO];    }}

以上是我的一些心得,希望可以帮助到别人,如果有不对的地方欢迎指正。

原创粉丝点击