前言
循环滚动是在目前我们开发中经常碰到的需求,而且网上有很多实现方式,但总是不能满足开发需要,闲来无事自己写了一个控件(GitHub下载),主要能实现以下功能:
1.循环滚动(水平/垂直方向)开启或关闭
2.自动滚动开启或关闭
3.自定义自动滚动时间间隔
4.用户自定义任何布局
5.用户自定义任何数据模型
6.自定义PgaeControl
7.自定义PgaeControl的指示器背景图
8.自定义PgaeControl的指示器间距
9.自定义PgaeControl的水平/垂直方向展示
10.自定义PgaeControl在控件中的位置
(1)水平方向的PgaeControl可以在上左、上中、上有、下左、下中和下右6个位置展示
(2)垂直方向的PgaeControl可以在左上、左中、左下、右上、右中和右下6个位置展示
更多功能等待你的发现……
代码说明
项目核心类有3个,分别是 LBCycleScrollView、LBPageControl 和 UICollectionViewCell+LBCycleScrollView。
LBCycleScrollView
LBCycleScrollView 类中实现循环滚动是的 UICollectionView。要点如下:
1.利用 UICollectionViewCell 的复用原理,当数据源的个数 >=3 的时候,UICollectionViewCell 只创建3个即可。
2.循环滚动的实现是将 UICollectionView 的 cell 个数加倍,即 2 x 数据源的个数。
3.使用 UIScrollView 的 setContentOffset:animated: 函数将控件滚动到争取的位置。
4.使用 NSTimer 实现自动滚动。
self.totalItemsCount = self.itemArray.count <= 1 ? self.itemArray.count : 2 * self.itemArray.count;
[self.collectionView reloadData];
if (self.totalItemsCount > 1) {
// scroll to the middle of the view
if (self.scrollDirection == LBCycleScrollViewScrollDirectionHorizontal) {
[self.collectionView setContentOffset:CGPointMake(self.totalItemsCount / 2 * self.collectionView.frame.size.width, 0.f) animated:NO];
} else {
[self.collectionView setContentOffset:CGPointMake(0.f, self.totalItemsCount / 2 * self.collectionView.frame.size.height) animated:NO];
}
self.pageControl.currentPage = self.currentIndex % self.itemArray.count;
[self startCycleScrollTimer];
}
属性解释:
// 自定义page control
@property (nonatomic, strong) LBPageControl *pageControl;
// 数据源
@property (nonatomic, strong) NSArray *itemArray;
// 将要注册给UICollectionView的UICollectionViewCell类
@property (nonatomic, strong) Class cellCls;
// 自动滚动的时间间隔,默认是5秒
@property (nonatomic) CGFloat scrollTimeInterval;
// page control 距离左或右边距的距离,默认是10.f
@property (nonatomic) CGFloat pageControlLeftOrRightMargin;
// page control 距离上或下边距的距离,默认是10.f
@property (nonatomic) CGFloat pageControlTopOrBottomMargin;
// page control 位置,默认是下方的左边
@property (nonatomic) LBCycleScrollViewPageControlAlignment pageControlAlignment;
// 滚动方向,默认是水平滚动
@property (nonatomic) LBCycleScrollViewScrollDirection scrollDirection;
// 循环滚动,默认开启
@property (nonatomic, getter=isCycleScrollEnabled) BOOL cycleScrollEnabled;
// 定时滚动,默认开启
@property (nonatomic, getter=isTimingScrollEnabled) BOOL timingScrollingEnabled;
方法解释:
// 实例化能无限滚动的对象,cls是注册给UICollectionView的类
+ (LBCycleScrollView *)cycleScrollViewWithFrame:(CGRect)frame cellClass:(Class)cls;
// 实例化不能无限滚动的对象,cls是注册给UICollectionView的类
+ (LBCycleScrollView *)nonCycleScrollViewWithFrame:(CGRect)frame cellClass:(Class)cls;
// 设置完数据源后重新加载
- (void)reloadData;
LBPageControl
LBPageControl 是在系统 UIPageControl 的基础上重写的类,多出的属性有:
// 正常状态的 page indicator 背景图
@property (nullable, nonatomic, strong) UIImage *pageIndicatorImage;
// 选中状态的 page indicator 背景图
@property (nullable, nonatomic, strong) UIImage *currentPageIndicatorImage;
// page control 的显示方向,默认是水平方向
@property (nonatomic) LBPageControlDirection pageControlDirection;
// page indicator 的间距
@property (nonatomic) CGFloat pageIndicatorSpacing;
UICollectionViewCell+LBCycleScrollView
UICollectionViewCell+LBCycleScrollView 显而易见是UICollectionViewCell 的一个分类,主要是添加了名为 cellItem 的属性和 assignmentValueToView 的函数。
1.cellItem 是 cell 要显示的数据。
2.assignmentValueToView 函数是将数据添加到 cell 的各个 view 上。
简单示例
1.定义数据模型。
#import
#import
@interface ExampleModel : NSObject
@property (nonatomic, strong) UIImage *image;
@property (nonatomic, strong) NSString *string;
@end
#import "ExampleModel.h"
@implementation ExampleModel
@end
2.定义 cell 类,导入 UICollectionViewCell+LBCycleScrollView。
#import UICollectionViewCell+LBCycleScrollView.h
@interface ExampleCell : UICollectionViewCell
@property (nonatomic, strong) UILabel *titleLabel;
@end
3.导入 cellItem 的数据模型类。 cell 类中自定义布局并赋值。
#import "ExampleCell.h"
#import "ExampleModel.h"
@interface ExampleCell ()
@property (nonatomic, strong) UIImageView *imageView;
@property (nonatomic, strong) UILabel *label;
@end
@implementation ExampleCell
- (instancetype)initWithFrame:(CGRect)frame {
if (self == [super initWithFrame:frame]) {
self.imageView = [[UIImageView alloc] initWithFrame:self.bounds];
[self.contentView addSubview:self.imageView];
CGFloat labelX = 10.f;
CGFloat labelH = 30.f;
self.label = [[UILabel alloc] initWithFrame:CGRectMake(labelX, frame.size.height - labelH, frame.size.width - labelX * 2, labelH)];
self.label.textColor = [UIColor whiteColor];
[self.contentView addSubview:self.label];
}
return self;
}
- (void)assignmentValueToView {
if ([self.cellItem isKindOfClass:[ExampleModel class]]) {
ExampleModel *model = (ExampleModel *)self.cellItem;
self.imageView.image = model.image;
self.label.text = model.string;
}
}
4.ViewController 中使用 LBCycleScrollView 提供的类方法创建对象,(LBPageControl 对象选择性创建),赋值并加载显示。
- (void)viewDidLoad {
[super viewDidLoad];
LBPageControl *control = [[LBPageControl alloc] init];
control.pageIndicatorImage = [UIImage imageNamed:@"control1"];
control.currentPageIndicatorImage = [UIImage imageNamed:@"control2"];
LBCycleScrollView *scrollView = [LBCycleScrollView cycleScrollViewWithFrame:CGRectMake(0.f, 0.f, self.view.frame.size.width, 200.f) cellClass:[ExampleCell class]];
scrollView.delegate = self;
scrollView.pageControl = control;
scrollView.pageControlAlignment = LBCycleScrollViewPageControlAlignmentRight | LBCycleScrollViewPageControlAlignmentBottom;
[self.view addSubview:scrollView];
ExampleModel *model1 = [ExampleModel new];
model1.image = [UIImage imageNamed:@"img1"];
model1.string = @"Bei Jing";
ExampleModel *model2 = [ExampleModel new];
model2.image = [UIImage imageNamed:@"img2"];
model2.string = @"Hong Kong";
ExampleModel *model3 = [ExampleModel new];
model3.image = [UIImage imageNamed:@"img3"];
model3.string = @"New York";
ExampleModel *model4 = [ExampleModel new];
model4.image = [UIImage imageNamed:@"img4"];
model4.string = @"Paris";
scrollView.itemArray = @[model1, model2, model3, model4];
[scrollView reloadData];
}
效果
使用方式
CocoaPods
1.在 Podfile 中添加 pod 'LBCycleScrollView'。
2.执行 pod install 或 pod update。
手动添加
1.下载 LBCycleScrollView 文件夹内的所有内容。
2.将 LBCycleScrollView 内的源文件添加(拖放)到你的工程
完善LBCycleScrollView
欢迎加入QQ群 541648808 讨论 LBCycleScrollView,交流问题、提出问题和解决问题。
如有错误,请指正。