今天给大家带来的是轮播图的实现(包括纵向轮播图,以及自定义 UIPageController),这里简单的讲述下轮播图的原理假如说,我现在有3张图片,正常是这样摆放的
那么我要想实现轮播的效果就需要在1前加个3,在3后面加个1顺序就是3`- 1 - 2 - 3 - 1`,这样的话当用户向左滑动时候当现实1`的时候,改变 scrollView 的 contentOffSet, 让他显示1,同理向右滑动的时候,当显示3`的时候改变 scrollView 的 contentOffSet, 让他显示3,(由于没有效果图,大家只能自行脑补一下了...... sorry,以后会补上的),
只要想明白了其中的逻辑,实现起来就比较方便了,下面是代码,还是只要将这两个文件之间导入到工程即可(这里要说明一下,由于为了使用的方便,这次封装的比较"狠",大家只要掉一行代码就可以实现,但是在使用的时候,请确保工程中已经导入了SDWebImage,因为在赋值图片的时候使用了它的方法,不导入的话是会报错滴..)
首先,自定义一个继承于UIView的类,(cycleScrollView)
//
// cycleScrollView.h
// cycleScrollView
//
// Created by Amydom on 16/12/16.
// Copyright © 2016年 Amydom. All rights reserved.
//
#import <UIKit/UIKit.h>
//imageView 的点击代理
@protocol cycleScrollViewDelegate <NSObject>
- (void)TouchImageViewToPush : (NSInteger) tag;
@end
@interface cycleScrollView : UIView
//创建轮播图
- (void)attributeForcycleScrollViewWithArray : (NSMutableArray *)dataArr
isCycleOrientation : (NSInteger)i;
//是否打开定时器
- (void)WhetherOpenTimer : (BOOL)isOpened;
@property (nonatomic , assign) id <cycleScrollViewDelegate>cycleDelegete;
@end
//
// cycleScrollView.m
// cycleScrollView
//
// Created by Amydom on 16/12/16.
// Copyright © 2016年 Amydom. All rights reserved.
//
#import "cycleScrollView.h"
#import "UIImageView+WebCache.h"
#import "cycleScrollModel.h"
#define Screen_W [UIScreen mainScreen].bounds.size.width
#pragma Mark - 判断轮播方向
typedef NS_ENUM(NSInteger, isCycle) {
//以下是枚举成员
HorizontalCycleScroll = 1,//横向
VerticalCycleScroll = 2,//纵向
};
@interface cycleScrollView()<UIScrollViewDelegate>{
UIScrollView *_scrollView;
UIPageControl *pageC;
NSMutableArray *_RotateArr;
UIView *_viewPage;
NSTimer *_time;
NSInteger Orientation;
BOOL _isOpen;
}
@end
@implementation cycleScrollView
- (instancetype)initWithFrame:(CGRect)frame{
if (self = [super initWithFrame:frame]) {
_scrollView = [[UIScrollView alloc]initWithFrame:frame];
[self addSubview:_scrollView];
[self attributeForScroll];
_isOpen = NO;
}
return self;
}
//轮播图创建
- (void)attributeForcycleScrollViewWithArray : (NSMutableArray *)dataArr isCycleOrientation : (NSInteger)i{
Orientation = i;
NSMutableArray *image_urlArr = [NSMutableArray array];
_RotateArr = [NSMutableArray arrayWithArray:dataArr];
//对数据进行遍历,来获取 url
if (_RotateArr.count != 0) {
for (int i = 0; i < _RotateArr.count; i++) {
cycleScrollModel *cycleModel = [_RotateArr objectAtIndex:i];
NSURL *url = [NSURL URLWithString:cycleModel.image_url];
[image_urlArr addObject:url];
}
}
NSURL *firstImageUrl = [image_urlArr lastObject];
NSURL *lastImageUrl = [image_urlArr objectAtIndex:0];
//insertObject插入
//UIMutableArray 执行 insertObject 操作时, 数组的长度会改变的,他会根据你指定的 index 去指定的位置将该元素插入数组,但是插入的同时, index 后面的所有元素都要往后排, 就跟排队有人插队是一个道理
[image_urlArr insertObject:firstImageUrl atIndex:0];
[image_urlArr addObject:lastImageUrl];
//判断方向
if (i == HorizontalCycleScroll) {
[_viewPage removeFromSuperview];//测试用
_scrollView.contentSize = CGSizeMake(Screen_W * (image_urlArr.count + 2), 0);
for (int i = 0; i < image_urlArr.count; i++) {
UIImageView *imageView = [[UIImageView alloc]initWithFrame:CGRectMake(Screen_W * i, 0, Screen_W, self.frame.size.height)];
imageView.userInteractionEnabled = YES;
[_scrollView addSubview:imageView];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(TapAction:)];
[imageView addGestureRecognizer:tap];
imageView.tag = 1000 + i;
[imageView sd_setImageWithURL:[image_urlArr objectAtIndex:i] placeholderImage:[UIImage imageNamed:@""]];
}
#pragma mark - 页码
pageC = [[UIPageControl alloc]initWithFrame:CGRectMake(Screen_W - 100, self.frame.size.height - 30, Screen_W / 7, 30)];
// pageC = [[UIPageControl alloc]initWithFrame:CGRectMake(Screen_W - 50, self.frame.size.height - 70, 30, self.frame.size.height / 7)];
pageC.backgroundColor = [UIColor clearColor];
[self addSubview:pageC];
//设置页码个数
pageC.numberOfPages = _RotateArr.count;
//点的颜色
pageC.currentPageIndicatorTintColor = [UIColor whiteColor];
pageC.pageIndicatorTintColor = [UIColor lightGrayColor];
//初始位置
pageC.currentPage = 0;
[pageC addTarget:self action:@selector(pageAction:) forControlEvents:UIControlEventValueChanged];
}
if (i == VerticalCycleScroll){
[pageC removeFromSuperview];//测试用
_scrollView.contentSize = CGSizeMake(0, self.frame.size.height * (image_urlArr.count + 2));
for (int i = 0; i < image_urlArr.count; i++) {
UIImageView *imageView = [[UIImageView alloc]initWithFrame:CGRectMake(0, self.frame.size.height * i, Screen_W, self.frame.size.height)];
imageView.userInteractionEnabled = YES;
[_scrollView addSubview:imageView];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(TapAction:)];
[imageView addGestureRecognizer:tap];
imageView.tag = 1000 + i;
[imageView sd_setImageWithURL:[image_urlArr objectAtIndex:i] placeholderImage:[UIImage imageNamed:@""]];
}
//自定义 pageController
[self customButton:_RotateArr.count];
}
}
- (void)WhetherOpenTimer : (BOOL)isOpened{
_isOpen = isOpened;
if (_isOpen) {
[self timerBegin];
}else{
[self timerClose];
}
}
//******************************私有方法***************************************
#pragma mark - 代理
- (void)TapAction:(UITapGestureRecognizer *)tap{
[self.cycleDelegete TouchImageViewToPush:tap.view.tag - 1000 - 1];
}
#pragma mark -- 页码切换
-(void)pageAction:(UIPageControl *)page{
[_scrollView setContentOffset:CGPointMake(Screen_W * (page.currentPage + 1), 0) animated:YES];
}
#pragma mark -- 图片无限循环(减速停止时触发)
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
if (Orientation == HorizontalCycleScroll) {
if (_scrollView.contentOffset.x == 0) {
_scrollView.contentOffset = CGPointMake(Screen_W * _RotateArr.count, 0);
}else if (_scrollView.contentOffset.x == Screen_W * (_RotateArr.count + 1)){
_scrollView.contentOffset = CGPointMake(Screen_W, 0);
}
pageC.currentPage = _scrollView.contentOffset.x / Screen_W - 1;
}
if (Orientation == VerticalCycleScroll){
if (_scrollView.contentOffset.y == 0){
_scrollView.contentOffset = CGPointMake(0, self.frame.size.height * _RotateArr.count);
}else if (_scrollView.contentOffset.y == self.frame.size.height * (_RotateArr.count + 1)){
_scrollView.contentOffset = CGPointMake(0, self.frame.size.height);
}
NSInteger tag = _scrollView.contentOffset.y / self.frame.size.height ;
//获取 view 上 tag 为3000的控件
UILabel *label = (UILabel *)[_viewPage viewWithTag:3000];
if (tag == 6) {//最后一张时,初始化位置
tag = 0;
label.frame = CGRectMake(0, 0, 6, 6);
}else{
label.frame = CGRectMake(0, tag * 15, 6, 6);
}
}
}
#pragma mark - 定时器开始
- (void)timerBegin{
if (!_time) {
_time = [NSTimer timerWithTimeInterval:3 target:self selector:@selector(changeAction:) userInfo:@"time" repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:_time forMode:NSRunLoopCommonModes];
}
}
- (void)timerClose{
[_time invalidate];
_time = nil;
}
#pragma mark -- 定时器触发
- (void)changeAction:(NSTimer *)time{
if (Orientation == HorizontalCycleScroll) {
[UIView animateWithDuration:0.5 animations:^{
[_scrollView setContentOffset:CGPointMake(_scrollView.contentOffset.x + Screen_W, 0) animated:YES];
pageC.currentPage = _scrollView.contentOffset.x / Screen_W;
}];
//循环(包括page)
//可以理解为到最后一张图就全部初始化
if (_scrollView.contentOffset.x == _RotateArr.count * Screen_W) {
//相当于初始化
_scrollView.contentOffset = CGPointMake(0, 0);
}
pageC.currentPage = _scrollView.contentOffset.x / Screen_W;
}
if (Orientation == VerticalCycleScroll) {
[UIView animateWithDuration:0.5 animations:^{
[_scrollView setContentOffset:CGPointMake(0 , _scrollView.contentOffset.y + self.frame.size.height) animated:YES];
}];
//循环(包括page)
//可以理解为到最后一张图就全部初始化
if (_scrollView.contentOffset.y == _RotateArr.count * self.frame.size.height) {
//相当于初始化
_scrollView.contentOffset = CGPointMake(0, 0);
}
NSInteger tag = _scrollView.contentOffset.y / self.frame.size.height + 1;
//获取 view 上 tag 为3000的控件
UILabel *label = (UILabel *)[_viewPage viewWithTag:3000];
if (tag == 6) {//最后一张时,初始化位置
tag = 0;
label.frame = CGRectMake(0, 0, 6, 6);
}else{
label.frame = CGRectMake(0, tag * 15, 6, 6);
}
}
}
#pragma mark -- 手指触碰时停止定时器
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
[self timerClose];
}
#pragma mark -- 手指离开继续滑动
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
if (_isOpen) {
[self timerBegin];
}
}
- (void)attributeForScroll{
_scrollView.delegate = self;
_scrollView.pagingEnabled = YES;
//用户交互
_scrollView.userInteractionEnabled = YES;
//取消边界反弹效果
_scrollView.bounces = NO;
//设置滑动条
_scrollView.showsHorizontalScrollIndicator = NO;
_scrollView.showsVerticalScrollIndicator = NO;
//初始偏移量为第二张图片
_scrollView.contentOffset = CGPointMake(Screen_W, 0);
}
#pragma mark - 自定义 pageController
- (void)customButton:(NSInteger)btnCount {
_viewPage = [[UIView alloc]initWithFrame:CGRectMake(Screen_W - 15, 60, 20, 100)];
[self addSubview:_viewPage];
for ( NSInteger i = 0; i < btnCount; i++) {
UIButton *button= [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(0, i*15, 6, 6);
button.clipsToBounds = YES;
button.layer.cornerRadius = 3;
button.tag = 1001+i;
button.backgroundColor = [UIColor grayColor];
[_viewPage addSubview:button];
}
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 6, 6)];
label.backgroundColor = [UIColor whiteColor];
label.clipsToBounds = YES;
label.tag = 3000;
label.layer.cornerRadius = 3;
[_viewPage addSubview:label];
}
@end
这是我关于轮播图的网络请求,我用到的就是这个圈上的数组,也就是拿到数据后的数组
之后之间调用下方法,传进刚才的数组,一切就都 OK 了..