ImageScrollView.h
#import <UIKit/UIKit.h>
/// 表示圖片滾動視圖的樣式
typedef enum {
ImageScrollType_Guide = 100, // 開機guide視圖樣式
ImageScrollType_Banner // banner欄樣式
}ImageScrollType;
/// 協議,觸發事件回調的方法
@protocol ImageScrollViewDelegate <NSObject>
@optional
/// “guide”樣式的最后一個視圖上的“立即體驗”按鈕觸發
-(void)experienceDidHandle;
/// “banner”樣式每一個圖片觸發回調的方法;index表示選中的圖片的下標
-(void)bannerImageDidHandleWithIndex:(NSInteger)index;
@end
@interface ImageScrollView : UIScrollView
/// 參數1:滾動視圖位置(建議以4.7寸屏設置); 參數2:樣式 ; 參數3:圖片名稱數組 ; 參數4:guide樣式的“立即體驗”按鈕標題;參數5:字體顏色 參數6:guide樣式的“立即體驗”按鈕位置;參數7:banner輪播圖時間間隔 ; 參數8:代理設置,用于觸發事件回調
-(instancetype)initWithFrame:(CGRect)frame
style:(ImageScrollType)type
images:(NSArray *)imgNameArr
confirmBtnTitle:(NSString *)title
confirmBtnTitleColor:(UIColor *)titleColor
confirmBtnFrame:(CGRect)btnFrame
autoScrollTimeInterval:(NSTimeInterval)interval
delegate:(id<ImageScrollViewDelegate>)delegate;
/// 給ImageScrollView的父視圖添加分頁控件,必須把ImageScrollView加為父視圖的子視圖之后再調用方法
-(void)addPageControlToSuperView:(UIView *)superView;
@end
ImageScrollView.m
#import "ImageScrollView.h"
#define SCR_W [UIScreen mainScreen].bounds.size.width // 屏幕寬度
#define SCR_H [UIScreen mainScreen].bounds.size.height // 屏幕高度
#define FIT_X(x) (SCR_W/375.*(x)) // 用于x軸適配
#define FIT_Y(y) (SCR_H/667.*(y)) // 用于y軸適配
@interface ImageScrollView ()<UIScrollViewDelegate>
{
ImageScrollType _type; // 樣式
NSString *_confirmBtnTitle; // 確認按鈕標題
CGRect _confirmBtnFrame; // 確認按鈕位置
UIColor *_confirmBtnTitleColor; // 確認按鈕標題顏色
NSUInteger _imgCount; // 圖片個數
CGFloat _disX; //在X軸的移動距離
}
@property(nonatomic,assign)id<ImageScrollViewDelegate>scDelegate;
@property(nonatomic,strong)NSTimer *myTimer; // 定時器
@property(nonatomic,strong)UIPageControl *pageCtl; // 分頁控件
@end
@implementation ImageScrollView
#pragma mark - 對外接口
/// 實例化方法
-(instancetype)initWithFrame:(CGRect)frame
style:(ImageScrollType)type
images:(NSArray *)imgNameArr
confirmBtnTitle:(NSString *)title
confirmBtnTitleColor:(UIColor *)titleColor
confirmBtnFrame:(CGRect)btnFrame
autoScrollTimeInterval:(NSTimeInterval)interval
delegate:(id<ImageScrollViewDelegate>)delegate {
self = [super initWithFrame:frame];
if (self) {
if (type == ImageScrollType_Guide)
{
// 設置內容視圖大小
self.contentSize = CGSizeMake(frame.size.width * imgNameArr.count, frame.size.height);
}
else
{
// 設置內容視圖大小
self.contentSize = CGSizeMake(frame.size.width * (imgNameArr.count+2), frame.size.height);
}
// 樣式賦值
_type = type;
// 圖片數量賦值
_imgCount = imgNameArr.count;
// guide樣式固定大小
if (type == ImageScrollType_Guide) {
self.frame = CGRectMake(0, 0, SCR_W, SCR_H);
self.contentSize = CGSizeMake(SCR_W * imgNameArr.count, SCR_H);
_confirmBtnTitle = title;
_confirmBtnFrame = btnFrame;
_confirmBtnTitleColor = titleColor;
}
// 隱藏滾動條
self.showsVerticalScrollIndicator = NO;
self.showsHorizontalScrollIndicator = NO;
// 開啟分頁屬性
self.pagingEnabled = YES;
// 設置UIScrollView代理
self.delegate = self;
// 設置自定義的代理
self.scDelegate = delegate;
// 添加圖片子視圖
[self addImageSubViews:imgNameArr];
// 添加定時器
if(type == ImageScrollType_Banner) {
self.myTimer = [NSTimer scheduledTimerWithTimeInterval:interval target:self selector:@selector(timerDidHandle:) userInfo:nil repeats:YES];
}
}
return self;
}
/// 添加分頁控件方法
-(void)addPageControlToSuperView:(UIView *)superView {
[superView addSubview:self.pageCtl];
}
#pragma mark - 分頁控制器實例化getter重寫
/// 添加分頁子視圖
-(UIPageControl *)pageCtl{
if (!_pageCtl) {
_pageCtl = [[UIPageControl alloc] initWithFrame:CGRectMake(0, 0, FIT_X(300), FIT_Y(25))];
if (_type == ImageScrollType_Guide)
{
_pageCtl.center = CGPointMake(SCR_W/2, SCR_H-FIT_Y(30));
}
else{
_pageCtl.center = CGPointMake(self.frame.origin.x + self.frame.size.width/2, self.frame.origin.y + self.frame.size.height-FIT_Y(25));
}
_pageCtl.pageIndicatorTintColor = [UIColor grayColor];
_pageCtl.currentPageIndicatorTintColor = [UIColor redColor];
_pageCtl.hidesForSinglePage = YES;
_pageCtl.numberOfPages = _imgCount;
_pageCtl.currentPage = 0;
}
return _pageCtl;
}
#pragma mark - 添加圖片子視圖
/// 添加圖片子視圖
-(void)addImageSubViews:(NSArray *)imgNameArr {
if (_type == ImageScrollType_Guide)
{
for (int i = 0; i<imgNameArr.count; i++) {
// 實例化圖形視圖
UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(0 + i * self.frame.size.width, 0, self.frame.size.width, self.frame.size.height)];
// 添加為滾動視圖的子視圖
[self addSubview:imgView];
// 設置圖形視圖的圖片
imgView.image = [UIImage imageNamed:imgNameArr[i]];
// 最后一個圖形視圖
if(i==imgNameArr.count-1){
imgView.userInteractionEnabled = YES;
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
btn.frame = _confirmBtnFrame;
[btn setTitle:_confirmBtnTitle forState:UIControlStateNormal];
[btn setTitleColor:_confirmBtnTitleColor forState:UIControlStateNormal];
[btn addTarget:self action:@selector(confirmBtnDidHandle:) forControlEvents:UIControlEventTouchUpInside];
[imgView addSubview:btn];
}
}
}
//banner樣式
else
{
for (int i = 0; i < imgNameArr.count+2; i++)
{
UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(0+self.frame.size.width*i, 0, self.frame.size.width, self.frame.size.height)];
//添加self的子視圖
[self addSubview:imgView];
if (i == 0) // 第一個圖片子視圖加載的是圖片數組中最后一張圖片
{
imgView.image = [UIImage imageNamed:imgNameArr[imgNameArr.count-1]];
imgView.tag = imgNameArr.count-1;
}
else if (i == imgNameArr.count +1)// 最后一個圖片子視圖加載的是圖片數組的第一張
{
imgView.image = [UIImage imageNamed:imgNameArr[0]];
imgView.tag = 0;
}
else // 中間圖片子視圖的圖片設置
{
imgView.image = [UIImage imageNamed:imgNameArr[i-1]];
imgView.tag = i-1;
}
imgView.userInteractionEnabled = YES;
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tapDidHandle:)];
[imgView addGestureRecognizer:tap];
//設定_disX的初始值
_disX = self.frame.size.width;
//設置子視圖的開始滾動位置
[self setContentOffset:CGPointMake(_disX, 0) animated:YES];
}
}
}
#pragma mark - 觸發方法
// 定時器觸發的方法
-(void)timerDidHandle:(NSTimer *)t {
_disX += self.frame.size.width;
[self scrollRectToVisible:CGRectMake(_disX, self.frame.origin.y, self.frame.size.width, self.frame.size.height) animated:YES];
}
/// guide最后視圖上的“立即體驗”按鈕觸發
-(void)confirmBtnDidHandle:(UIButton *)btn {
if ([self.scDelegate respondsToSelector:@selector(experienceDidHandle)]) {
[self.scDelegate experienceDidHandle];
}
}
/// banner圖片點擊后觸發
-(void)tapDidHandle:(UITapGestureRecognizer *)tap {
// 獲取觸發了該點擊手勢的視圖對象
UIView *tapView = tap.view;
if (![tapView isKindOfClass:[UIImageView class]]) {
return;
}
NSInteger tag = tapView.tag;
if ([self.scDelegate respondsToSelector:@selector(bannerImageDidHandleWithIndex:)]) {
[self.scDelegate bannerImageDidHandleWithIndex:tag];
}
}
#pragma mark - UIScrollViewDelegate
-(void)scrollViewDidScroll:(UIScrollView *)scrollView {
//guide樣式
if (_type == ImageScrollType_Guide)
{
// 獲取滾動視圖滾動的距離
CGPoint pos = scrollView.contentOffset;
// 獲取當前的分頁的下標
NSInteger index = (int)(pos.x/self.frame.size.width);
// 改變分頁控制器的當前下標
self.pageCtl.currentPage = index;
}
//banner樣式
else
{
// 獲取滾動視圖滾動的距離
CGPoint pos = scrollView.contentOffset;
//賦值
_disX = pos.x;
//如果滾動到第一個圖片子視圖將內容視圖的起始位置變換置倒數第二張圖的位置
if (_disX == 0)
{
[self setContentOffset:CGPointMake(self.frame.size.width*_imgCount, 0) animated:NO];
}
else if (_disX == self.frame.size.width * (_imgCount+1))
{
[self setContentOffset:CGPointMake(self.frame.size.width, 0) animated:NO];
}
/*
設置分頁控制器當前分頁
*/
//最后一張圖的點
if (_disX == 0 || _disX == self.frame.size.width*_imgCount)
{
self.pageCtl.currentPage = _imgCount-1;
}
//第一張圖片
else if (_disX == self.frame.size.width || _disX == self.frame.size.width * (_imgCount+1))
{
self.pageCtl.currentPage = 0;
}
//其他圖片
else
{
self.pageCtl.currentPage = (int)(_disX / self.frame.size.width)-1;
}
}
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
// Drawing code
}
*/
@end
引導頁控制器使用代碼
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
NSArray *imgArr = @[@"guidePage1",@"guidePage2",@"guidePage3"];
ImageScrollView *imgScrView = [[ImageScrollView alloc]initWithFrame:CGRectNull style:ImageScrollType_Guide images:imgArr confirmBtnTitle:@"立即體驗" confirmBtnTitleColor:[UIColor whiteColor] confirmBtnFrame:CGRectMake(230, 10, 100, 40) autoScrollTimeInterval:0 delegate:self];
[self.view addSubview:imgScrView];
[imgScrView addPageControlToSuperView:self.view];
}
//內容可自定義
- (void)experienceDidHandle{
//1)切換窗口的根視圖控制器
AppDelegate *app = (AppDelegate *)[UIApplication sharedApplication].delegate;
app.window.rootViewController = app.sideMenu;
//2)把當前版本號持久化
[[NSUserDefaults standardUserDefaults]setObject:CURRENT_VERSION forKey:SAVED_VERSION];
[[NSUserDefaults standardUserDefaults]synchronize];
}
無限輪播控制器使用代碼
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
NSArray *imgArr = @[@"man1.JPG",@"man2.JPG",@"man3.JPG",@"man4.JPG"];
CGFloat scrW = [UIScreen mainScreen].bounds.size.width;
ImageScrollView *imgScrView = [[ImageScrollView alloc]initWithFrame:CGRectMake(10, 100, scrW-20, 250) style:ImageScrollType_Banner images:imgArr confirmBtnTitle:nil confirmBtnTitleColor:nil confirmBtnFrame:CGRectNull autoScrollTimeInterval:3.0 delegate:self];
[self.view addSubview:imgScrView];
[imgScrView addPageControlToSuperView:self.view];
//使用Scrollview與Navigation使用會出現坐標位置不齊,所以使用以下方法可調整
self.edgesForExtendedLayout = UIRectEdgeNone;
}
- (void)bannerImageDidHandleWithIndex:(NSInteger)index
{
NSLog(@"===%ld",index);
}
導航條與UIScrollView沖突解決方法
(1)在添加UIScrollView的ViewController中添加代碼
self.edgesForExtendedLayout = UIRectEdgeNone;
(2)在添加UIScrollView的ViewController中添加代碼
self.automaticallyAdjustsScrollViewInsets = YES;
(3)如果以上兩種方法都不可以解決,使用下面方法:
在添加UIScrollView的ViewController中添加代碼:
UIView *v = [[UIView alloc] init];
[self.view addSubview:v];
然后再正常添加UIScrollView即可