OC 引导页轮播图&无限轮播(第三方)

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即可
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容