一、控制器里只需要写下边的代码
#import "ViewController.h"
#import "JWCycleCollectionView.h"
#import "JWPageControl.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 创建轮播视图
JWCycleCollectionView *cycleView = [[JWCycleCollectionView alloc] initWithUrlString:@"http://c.m.163.com/nc/ad/headline/0-4.html"];
cycleView.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 200);
[self.view addSubview:cycleView];
// 创建pageControl
JWPageControl *pageControl = [[JWPageControl alloc] initWithFrame:CGRectMake(cycleView.frame.size.width - 100, cycleView.frame.size.height - 42, 100, 50)];
[self.view addSubview:pageControl];
cycleView.pageControl = pageControl;
}
二、加载网络请求的工具类和数据模型
1.工具类
定义一个供外界调用的方法,传入URLString,网络加载到数据后用自定义的block实现回调。
#import "AFHTTPSessionManager.h"
typedef void(^finishBlock)(id result);
@interface WJWNetWorkTool : AFHTTPSessionManager
// 获取单例的方法
+ (instancetype)sharedWJWNetWorkTool;
// 供所有模型调用的方法,模型传进来URLString和回调,当从网络上回来结果之后,~~传给模型
- (void)objectWithURLString:(NSString *)URLString andFinishedBlock:(finishBlock)finishblock;
@end
#import "WJWNetWorkTool.h"
@implementation WJWNetWorkTool
#if DEBUG
static NSString *BaseURLString = @"http://c.m.163.com/";
#else
static NSString *BaseURLString = @"http://xxxxxxxxx/";
#endif
+ (instancetype)sharedWJWNetWorkTool{
static dispatch_once_t onceToken;
static WJWNetWorkTool *_instance = nil;
dispatch_once(&onceToken, ^{
_instance = [[self alloc] initWithBaseURL:[NSURL URLWithString:BaseURLString]];
// 该默认响应方式支持的类型
_instance.responseSerializer.acceptableContentTypes = [_instance.responseSerializer.acceptableContentTypes setByAddingObject:@"text/html"];
});
return _instance;
}
- (void)objectWithURLString:(NSString *)URLString andFinishedBlock:(finishBlock)finishblock{
// AFN去发送网络请求
[self GET:URLString parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
// 通过block传递给模型
if (finishblock) {
// NSLog(@"%@",responseObject);
finishblock(responseObject);
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@"error:%@",[error localizedDescription]);
}];
}
@end
2.数据模型
定义一个供外界调用的方法,传入urlString,调用网络工具类加载数据,加载到数据后在回调的finishblock中将加载到的数据进行字典转模型。此外,定义了completeBlock供回调,将模型数组传递到调用block的位置。
#import <Foundation/Foundation.h>
typedef void(^completeBlock)(NSArray *cyclePictures);
@interface JWCycle : NSObject
/**
* 标题
*/
@property (nonatomic,copy) NSString *title;
/**
* 图片地址
*/
@property (nonatomic,copy) NSString *imgsrc;
/**
* 根据网址加载网络数据
*
* @param urlString 网址
* @param completeBlcok 回调的block
*/
+ (void)cylcesWithURLsting:(NSString *)urlString completeBLock:(completeBlock)completeBlcok;
@end
#import "JWCycle.h"
#import "WJWNetWorkTool.h"
@implementation JWCycle
+ (instancetype)cycleWithDict:(NSDictionary *)dict{
id obj = [[self alloc] init];
[obj setValuesForKeysWithDictionary:dict];
return obj;
}
- (void)setValue:(id)value forUndefinedKey:(NSString *)key{}
+ (void)cylcesWithURLsting:(NSString *)urlString completeBLock:(completeBlock)completeBlcok{
[[WJWNetWorkTool sharedWJWNetWorkTool] objectWithURLString:urlString andFinishedBlock:^(id result) {
NSDictionary *dict = (NSDictionary *)result;
// NSLog(@"%@",dict);
NSArray *dictArr = dict[@"headline_ad"];
NSMutableArray *arrM = [NSMutableArray arrayWithCapacity:dictArr.count];
[dictArr enumerateObjectsUsingBlock:^(NSDictionary * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
JWCycle *cycle = [JWCycle cycleWithDict:obj];
[arrM addObject:cycle];
}];
// NSLog(@"%@",arrM);
if (completeBlcok) {
completeBlcok(arrM.copy);
}
}];
}
二、自定义UICollectionView、UICollectionViewFlowlayout和UICollectionViewCell
1.UICollectionView
定义一个供外界调用地方法,传入URLString,加载图片和title等;另外定义一个pageControl属性,与控制器创建的pageControl进行关联。
#import <UIKit/UIKit.h>
#import "JWPageControl.h"
@interface JWCycleCollectionView : UICollectionView
// 传入加载图片的网址,加载到的数据应包含每张图片的网址以
- (instancetype)initWithUrlString:(NSString *)urlString;
// 分页控制器
@property (nonatomic,weak) JWPageControl *pageControl;
@end
#import "JWCycleCollectionView.h"
#import "JWCycle.h"
#import "JWCycleCollectionViewCell.h"
#import "JWCycleCollectionViewLayout.h"
#define KSectionCount 100
#define KScreenWidth [UIScreen mainScreen].bounds.size.width
@interface JWCycleCollectionView ()<UICollectionViewDataSource,UICollectionViewDelegate>
// 存储轮播数据模型的数组
@property (nonatomic,strong) NSArray <JWCycle *>*cycles;
// 流布局
@property (weak, nonatomic) UICollectionViewFlowLayout *flowLayout;
// 定时器
@property (nonatomic,strong) NSTimer *timer;
@end
@implementation JWCycleCollectionView
static NSString * const reuseIdentifier = @"Cell";
- (instancetype)initWithUrlString:(NSString *)urlString{
self = [super initWithFrame:CGRectZero collectionViewLayout:[[JWCycleCollectionViewLayout alloc] init]];
if (self) {
self.dataSource = self;
self.delegate = self;
[self registerClass:[JWCycleCollectionViewCell class] forCellWithReuseIdentifier:reuseIdentifier];
[self loadDataWithUrlString:urlString];
}
return self;
}
- (void)loadDataWithUrlString:(NSString *)urlString{
__weak typeof(self) weakSelf = self;
[JWCycle cylcesWithURLsting:urlString completeBLock:^(NSArray *cyclePictures) {
// NSLog(@"加载到数据了");
weakSelf.cycles = cyclePictures;
[weakSelf reloadData];
// 默认选中中间那一组
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:KSectionCount / 2];
[weakSelf scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionLeft animated:NO];
[self timer];
self.pageControl.cycles = cyclePictures;
}];
}
#pragma mark <UICollectionViewDataSource>
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{
return KSectionCount;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return self.cycles.count;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
JWCycleCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
JWCycle *cycle = self.cycles[indexPath.item];
cell.cycle = cycle;
return cell;
}
#pragma mark - 定时器
- (NSTimer *)timer{
if (!_timer) {
_timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(nextPage) userInfo:nil repeats:YES];
// 添加到主运行循环
[[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSRunLoopCommonModes];
}
return _timer;
}
- (void)nextPage{
NSIndexPath *indexPath = [[self indexPathsForVisibleItems] lastObject];
// 中间那组的索引
NSIndexPath *middleIndexPath = [NSIndexPath indexPathForItem:indexPath.item inSection:(KSectionCount / 2)];
[self scrollToItemAtIndexPath:middleIndexPath atScrollPosition:UICollectionViewScrollPositionLeft animated:NO];
if (middleIndexPath.item != self.cycles.count - 1){
middleIndexPath = [NSIndexPath indexPathForItem:(indexPath.item +1) inSection:middleIndexPath.section];
} else{
middleIndexPath = [NSIndexPath indexPathForItem:0 inSection:middleIndexPath.section+1];
}
[self scrollToItemAtIndexPath:middleIndexPath atScrollPosition:UICollectionViewScrollPositionLeft animated:YES];
}
#pragma mark <UIScrollViewDelegate>
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{
[self.timer invalidate];
self.timer = nil;
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{
if (decelerate == NO) { // 没有降速的过程,直接在此方法中去添加定时器
[self timer];
}
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
[self timer];
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
// 确定当前页数及组数
NSInteger currentPage = self.contentOffset.x / KScreenWidth;
NSInteger currentPageIndex = currentPage % self.cycles.count;
self.pageControl.currentPage = currentPageIndex;
}
@end
2.UICollectionViewFlowlayout
在自定义的UICollectionView初始化的时候,将自定义的UICollectionViewflowlayout设置给UICollectionView。
#import "JWCycleCollectionViewLayout.h"
@implementation JWCycleCollectionViewLayout
- (void)prepareLayout{
[super prepareLayout];
// 直接利用 collectionView 的属性设置布局
self.itemSize = self.collectionView.bounds.size;
self.minimumInteritemSpacing = 0;
self.minimumLineSpacing = 0;
self.scrollDirection = UICollectionViewScrollDirectionHorizontal;
self.collectionView.bounces = NO;
self.collectionView.pagingEnabled = YES;
self.collectionView.showsHorizontalScrollIndicator = NO;
self.collectionView.showsVerticalScrollIndicator = NO;
}
@end
3.UICollectionViewCell
重写传入的数据模型的set方法,给cell里的imageView和titileLabel赋值。
#import <UIKit/UIKit.h>
@class JWCycle;
@interface JWCycleCollectionViewCell : UICollectionViewCell
// 轮播数据模型
@property (nonatomic,strong) JWCycle *cycle;
@end
#import "JWCycleCollectionViewCell.h"
#import "Masonry.h"
#import "UIImageView+WebCache.h"
#import "JWCycle.h"
@implementation JWCycleCollectionViewCell{
UIImageView *_iconView;
UILabel *_titleLabel;
}
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
//NSLog(@"%@", NSStringFromCGRect(frame));
_iconView = [[UIImageView alloc] initWithFrame:self.bounds];
[self.contentView addSubview:_iconView];
_titleLabel = [[UILabel alloc] init];
_titleLabel.textColor = [UIColor whiteColor];
_titleLabel.font = [UIFont systemFontOfSize:15];
[self.contentView addSubview:_titleLabel];
[_titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.contentView).offset(12);
make.bottom.equalTo(self.contentView).offset(-10);
}];
}
return self;
}
- (void)setCycle:(JWCycle *)cycle{
_cycle = cycle;
[_iconView sd_setImageWithURL:[NSURL URLWithString:cycle.imgsrc]];
_titleLabel.text = cycle.title;
}
@end
三、UIPageControl
UIPageControl不能直接添加到UICollectionView上,只能添加到控制器的View上。拿到模型数组,并且重写其set方法设置一共显示多少个圆点(多少也)
#import <UIKit/UIKit.h>
@interface JWPageControl : UIPageControl
@property (nonatomic,strong) NSArray *cycles;
@end
#import "JWPageControl.h"
@implementation JWPageControl
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// 设置非选中页的圆点颜色
self.pageIndicatorTintColor = [UIColor redColor];
// 设置选中页的圆点颜色
self.currentPageIndicatorTintColor = [UIColor blueColor];
// 禁止默认的点击功能
self.enabled = NO;
}
return self;
}
- (void)setCycles:(NSArray *)cycles{
_cycles = cycles;
self.numberOfPages = cycles.count; // 一共显示多少个圆点(多少页)
}
@end