现在开发中,滚动视图的使用应该说是很频繁的了,像tableView上面嵌套滚动视图,常规界面上添加滚动视图都是很常见的,但是要实现出一个多方通用且不怎么占用类存的却不是那么容易的了,本文(博主第一次写,有不周地方还请大家指出来)将用代码加注释的方式教您写出一篇属于自己的极限优化的scrollView;好了废话不多说,直接上代码。
步骤:首先需要在.h中添加两个代理方法,方便外部实现图片监控,然后需要在.h中申明常用属性,及外部调用的接口
//
// WYScrollView.h
// 无忧学堂
//
// Created by jacke-xu on 16/2/22.
// Copyright © 2016年 jacke-xu. All rights reserved.
//
/********************************************************************************************* *******希望能帮助到需要的人,但还请转载注明出处:****************************************************************************************************/
#import <UIKit/UIKit.h>
/** 遵循该代理就可以监控到网络滚动视图的index*/
@protocol WYScrollViewNetDelegate <NSObject>
@optional
/** 点中网络滚动视图后触发*/
-(void)didSelectedNetImageAtIndex:(NSInteger)index;
@end
/** 遵循该代理就可以监控到本地滚动视图的index*/
@protocol WYScrollViewLocalDelegate <NSObject>
@optional
/** 点中本地滚动视图后触发*/
-(void)didSelectedLocalImageAtIndex:(NSInteger)index;
@end
@interface WYScrollView : UIView
/** 选中网络图片的索引*/ @property (nonatomic, strong) id <WYScrollViewNetDelegate> netDelagate; /** 选中本地图片的索引*/ @property (nonatomic, strong) id <WYScrollViewLocalDelegate> localDelagate; /** 占位图*/ @property (nonatomic, strong) UIImage *placeholderImage; /** 滚动延时*/ @property (nonatomic, assign) NSTimeInterval AutoScrollDelay; /** * 本地图片 * * @param frame 位置 * @param imageArray 加载本地图片 * * @return */ - (instancetype) initWithFrame:(CGRect)frame WithLocalImages:(NSArray *)imageArray; /** * 加载网络图片 * * @param frame 位置大小 * @param imageArray 名字 * * @return */ - (instancetype) initWithFrame:(CGRect)frame WithNetImages:(NSArray *)imageArray; @end
接下来我们到.m中把他们实现出来
//
// WYScrollView.m
// 无忧学堂
//
// Created by jacke-xu on 16/2/22.
// Copyright © 2016年 jacke-xu. All rights reserved.
//
#import "WYScrollView.h"
#import "UIImageView+WebCache.h"
#define pageSize 16
//获得RGB颜色
#define RGBA(r, g, b, a) [UIColor colorWithRed:r/255.0f green:g/255.0f blue:b/255.0f alpha:a]
#define RGB(r, g, b) RGBA(r, g, b, 1.0f)
#define pageColor RGB(67, 199, 176)
/** 滚动宽度*/
#define ScrollWidth self.frame.size.width
/** 滚动高度*/
#define ScrollHeight self.frame.size.height
@interface WYScrollView () <UIScrollViewDelegate>
@property (nonatomic, copy) NSArray *imageArray;
@end
@implementation WYScrollView
{
__weak UIImageView *_leftImageView,*_centerImageView,*_rightImageView;
__weak UIScrollView *_scrollView;
__weak UIPageControl *_PageControl; NSTimer *_timer; /** 当前显示的是第几个*/ NSInteger _currentIndex; /** 图片个数*/ NSInteger _MaxImageCount; /** 是否是网络图片*/ BOOL _isNetworkImage; } #pragma mark - 本地图片 -(instancetype)initWithFrame:(CGRect)frame WithLocalImages:(NSArray *)imageArray { if (imageArray.count < 2 ) { return nil; } self = [super initWithFrame:frame]; if ( self) { _isNetworkImage = NO; /** 创建滚动view*/ [self createScrollView]; /** 加入本地image*/ [self setImageArray:imageArray]; /** 设置数量*/ [self setMaxImageCount:_imageArray.count]; } return self; } #pragma mark - 网络图片 -(instancetype)initWithFrame:(CGRect)frame WithNetImages:(NSArray *)imageArray { if (imageArray.count < 2 ) { return nil; } self = [super initWithFrame:frame]; if ( self) { _isNetworkImage = YES; /** 创建滚动view*/ [self createScrollView]; /** 加入本地image*/ [self setImageArray:imageArray]; /** 设置数量*/ [self setMaxImageCount:_imageArray.count]; } return self; } #pragma mark - 设置数量 -(void)setMaxImageCount:(NSInteger)MaxImageCount { _MaxImageCount = MaxImageCount; /** 复用imageView初始化*/ [self initImageView]; /** pageControl*/ [self createPageControl]; /** 定时器*/ [self setUpTimer]; /** 初始化图片位置*/ [self changeImageLeft:_MaxImageCount-1 center:0 right:1]; } - (void)createScrollView { UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:self.bounds]; [self addSubview:scrollView]; scrollView.backgroundColor = [UIColor clearColor]; scrollView.pagingEnabled = YES; scrollView.showsHorizontalScrollIndicator = NO; scrollView.delegate = self; /** 复用,创建三个*/ scrollView.contentSize = CGSizeMake(ScrollWidth * 3, 0); /** 设置滚动延时时间*/ _AutoScrollDelay = 0; /** 开始显示的是第一个 前一个是最后一个 后一个是第二张*/ _currentIndex = 0; _scrollView = scrollView; } -(void)setImageArray:(NSArray *)imageArray { //如果是网络 if (_isNetworkImage) { _imageArray = [imageArray copy]; }else { //本地 NSMutableArray *localimageArray = [NSMutableArray arrayWithCapacity:imageArray.count]; for (NSString *imageName in imageArray) { [localimageArray addObject:[UIImage imageNamed:imageName]]; } _imageArray = [localimageArray copy]; } } - (void)initImageView { UIImageView *leftImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0,ScrollWidth, ScrollHeight)]; UIImageView *centerImageView = [[UIImageView alloc] initWithFrame:CGRectMake(ScrollWidth, 0,ScrollWidth, ScrollHeight)]; UIImageView *rightImageView = [[UIImageView alloc] initWithFrame:CGRectMake(ScrollWidth * 2, 0,ScrollWidth, ScrollHeight)]; centerImageView.userInteractionEnabled = YES; [centerImageView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(imageViewDidTap)]]; [_scrollView addSubview:leftImageView]; [_scrollView addSubview:centerImageView]; [_scrollView addSubview:rightImageView]; _leftImageView = leftImageView; _centerImageView = centerImageView; _rightImageView = rightImageView; } //点击事件 - (void)imageViewDidTap { [self.netDelagate didSelectedNetImageAtIndex:_currentIndex]; [self.localDelagate didSelectedLocalImageAtIndex:_currentIndex]; } -(void)createPageControl { UIPageControl *pageControl = [[UIPageControl alloc] initWithFrame:CGRectMake(0,ScrollHeight - pageSize,ScrollWidth, 8)]; //设置页面指示器的颜色 pageControl.pageIndicatorTintColor = [UIColor lightGrayColor]; //设置当前页面指示器的颜色 pageControl.currentPageIndicatorTintColor = pageColor; pageControl.numberOfPages = _MaxImageCount; pageControl.currentPage = 0; [self addSubview:pageControl]; _PageControl = pageControl; } #pragma mark - 定时器 - (void)setUpTimer { if (_AutoScrollDelay < 0.5) return;//太快了 _timer = [NSTimer timerWithTimeInterval:_AutoScrollDelay target:self selector:@selector(scorll) userInfo:nil repeats:YES]; [[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSRunLoopCommonModes]; } - (void)scorll { [_scrollView setContentOffset:CGPointMake(_scrollView.contentOffset.x +ScrollWidth, 0) animated:YES]; } #pragma mark - 给复用的imageView赋值 - (void)changeImageLeft:(NSInteger)LeftIndex center:(NSInteger)centerIndex right:(NSInteger)rightIndex { if (_isNetworkImage) { [_leftImageView sd_setImageWithURL:[NSURL URLWithString:_imageArray[LeftIndex]] placeholderImage:_placeholderImage]; [_centerImageView sd_setImageWithURL:[NSURL URLWithString:_imageArray[centerIndex]] placeholderImage:_placeholderImage]; [_rightImageView sd_setImageWithURL:[NSURL URLWithString:_imageArray[rightIndex]] placeholderImage:_placeholderImage]; }else { _leftImageView.image = _imageArray[LeftIndex]; _centerImageView.image = _imageArray[centerIndex]; _rightImageView.image = _imageArray[rightIndex]; } [_scrollView setContentOffset:CGPointMake(ScrollWidth, 0)]; } #pragma mark - 滚动代理 - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate { [self setUpTimer]; } - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { [self removeTimer]; } - (void)removeTimer { if (_timer == nil) return; [_timer invalidate]; _timer = nil; } - (void)scrollViewDidScroll:(UIScrollView *)scrollView { //开始滚动,判断位置,然后替换复用的三张图 [self changeImageWithOffset:scrollView.contentOffset.x]; } - (void)changeImageWithOffset:(CGFloat)offsetX { if (offsetX >= ScrollWidth * 2) { _currentIndex++; if (_currentIndex == _MaxImageCount-1) { [self changeImageLeft:_currentIndex-1 center:_currentIndex right:0]; }else if (_currentIndex == _MaxImageCount) { _currentIndex = 0; [self changeImageLeft:_MaxImageCount-1 center:0 right:1]; }else { [self changeImageLeft:_currentIndex-1 center:_currentIndex right:_currentIndex+1]; } _PageControl.currentPage = _currentIndex; } if (offsetX <= 0) { _currentIndex--; if (_currentIndex == 0) { [self changeImageLeft:_MaxImageCount-1 center:0 right:1]; }else if (_currentIndex == -1) { _currentIndex = _MaxImageCount-1; [self changeImageLeft:_currentIndex-1 center:_currentIndex right:0]; }else { [self changeImageLeft:_currentIndex-1 center:_currentIndex right:_currentIndex+1]; } _PageControl.currentPage = _currentIndex; } } -(void)dealloc { [self removeTimer]; } #pragma mark - set方法,设置间隔时间 - (void)setAutoScrollDelay:(NSTimeInterval)AutoScrollDelay { _AutoScrollDelay = AutoScrollDelay; [self removeTimer]; [self setUpTimer]; } /* // Only override drawRect: if you perform custom drawing. // An empty implementation adversely affects performance during animation. - (void)drawRect:(CGRect)rect { // Drawing code } */ @end
最后教大家怎么调用本文接口
//
// ViewController.m
// WYScrollView
//
// Created by Jacke-xu on 16/3/10.
// Copyright © 2016年 Jacke-xu. All rights reserved.
//
#import "ViewController.h"
#import "WYScrollView.h"
@interface ViewController ()<WYScrollViewLocalDelegate,WYScrollViewNetDelegate>
/** 网络图片数组*/
@property(nonatomic,strong)NSArray *NetImageArray;
/** 本地图片数组*/
@property(nonatomic,strong)NSArray *localImageArray;
@end
@implementation ViewController
-(NSArray *)NetImageArray { if(!_NetImageArray) { _NetImageArray = @[@"http://ws.xzhushou.cn/focusimg/201508201549023.jpg",@"http://ws.xzhushou.cn/focusimg/52.jpg",@"http://ws.xzhushou.cn/focusimg/51.jpg",@"http://ws.xzhushou.cn/focusimg/50.jpg"]; } return _NetImageArray; } -(NSArray *)localImageArray { if(!_localImageArray) { _localImageArray = @[@"1",@"2",@"3",@"4",@"5",@"6",@"7",@"8",@"9"]; } return _localImageArray; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. /** 创建网络滚动视图*/ [self createNetScrollView]; /** 创建本地滚动视图*/ [self createLocalScrollView]; } -(void)createNetScrollView { /** 设置网络scrollView的Frame及所需图片*/ WYScrollView *WYNetScrollView = [[WYScrollView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 200) WithNetImages:self.NetImageArray]; /** 设置滚动延时*/ WYNetScrollView.AutoScrollDelay = 3; /** 设置占位图*/ WYNetScrollView.placeholderImage = [UIImage imageNamed:@"placeholderImage"]; /** 获取网络图片的index*/ WYNetScrollView.netDelagate = self; /** 添加到当前View上*/ [self.view addSubview:WYNetScrollView]; } -(void)createLocalScrollView { /** 设置本地scrollView的Frame及所需图片*/ WYScrollView *WYLocalScrollView = [[WYScrollView alloc]initWithFrame:CGRectMake(0, 220, self.view.frame.size.width, 200) WithLocalImages:self.localImageArray]; /** 设置滚动延时*/ WYLocalScrollView.AutoScrollDelay = 2; /** 获取本地图片的index*/ WYLocalScrollView.localDelagate = self; /** 添加到当前View上*/ [self.view addSubview:WYLocalScrollView]; } /** 获取网络图片的index*/ -(void)didSelectedNetImageAtIndex:(NSInteger)index { NSLog(@"点中网络图片的下标是:%ld",(long)index); } /** 获取本地图片的index*/ -(void)didSelectedLocalImageAtIndex:(NSInteger)index { NSLog(@"点中本地图片的下标是:%ld",(long)index); } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end