• iOS --- 轮播图


    在iOS开发中,有很多项目使用到了轮播图,通常我们更多的是使用一些别人写的方法来实现,当然这样也更加快捷和方便,但其中的实现原理却一窍不通,最近对轮播图研究了一番,也试着去实现了一些基本的功能,下面就让我来介绍一下:

    本文中的轮播图主要是实用UIScrollView + NSTimer来实现的,具体思路是:首先我们先创建一个UIScrollView,根据图片的数据设置UIScrollView的内容尺寸(因为要实现无限轮播的的效果,需要多设置一个宽度的内容尺寸来起到缓冲的作用,使其显示到最后一张时,当我们再次滑动,直接跳转到第一张,即UIScrollView的内容尺寸为图片数据总和再加1,下面会详细介绍),然后创建一个UIPageControl来现实图片的具体位置,并让其与UIScrollView起到联动的效果。最后创建一个定时器,每隔一段时间设置UIScrollView的偏移量,注意也要更改UIPageControl的选中页位置。当然这种方法主要适用于数据较少的时候使用,当数据较多时,我们就要考虑复用的问题了。

    首先确定数据源,这里我们使用本地数据,创建图片数组来存放五张图片

    1  _imgArray = @[@"01.jpg", @"02.jpg", @"03.jpg", @"04.jpg", @"05.jpg"];

    创建UIScrollView和UIPageControl,注意UIScrollView的内容尺寸为_imgArray.count + 1,UIScrollView的最后一个位置要放置地一张图片

     1 _scrollView = [[UIScrollView alloc]initWithFrame:CGRctMake(0, 0, kScreenWidth, 200)];
     2     _scrollView.contentSize = CGSizeMake(kScreenWidth * (_imgArray.count + 1), 200);
     3     _scrollView.pagingEnabled = YES;
     4     _scrollView.delegate = self;
     5     _scrollView.showsHorizontalScrollIndicator = NO;
     6     //创建子视图
     7     for (int i = 0; i < _imgArray.count + 1; i++) {
     8         UIImageView *imgView = [[UIImageView alloc]initWithFrame:CGRectMake(0 + i * kScreenWidth, 0, kScreenWidth, 200)];
     9         if (i == _imgArray.count) {
    10             imgView.image = [UIImage imageNamed:_imgArray[0]];
    11         }else{
    12           imgView.image = [UIImage imageNamed:_imgArray[i]];
    13         } 
    14         [_scrollView addSubview:imgView];
    15     }
    16     [self.view addSubview:_scrollView];
    17     
    18     //创建分页控件
    19     _pageCtrl = [[UIPageControl alloc]initWithFrame:CGRectMake((kScreenWidth - 130)/2, _scrollView.bottom - 20, 130, 15)];
    20     //_pageCtrl.backgroundColor = [UIColor cyanColor];
    21     _pageCtrl.numberOfPages = _imgArray.count;
    22     _pageCtrl.currentPage = 0;
    23     [self.view addSubview:_pageCtrl];

    实现UIScrollView的代理方法 - (void)scrollViewDidScroll:(UIScrollView *)scrollView,在此方法中可以获取到scrollView的偏移量,根据偏移量获取分页位置。假设屏幕宽度为320,根据上图可明显得出,当向右滑动xOff为1600时,UIScrollView恰好滑到了最后一个索引处,即第一张图片。此时如果我们不添加处理,继续向右滑动,没有图片,这不是我们想要的结果。无限循环滑动才是我们的目的,此时,我们想看到的是第二张图片,索引为1。因此,当xOff大于1600 的瞬间,设置UIScrollView的偏移量为CGPointMake(0, 0),此时我们看到的仍然是第一张图片,但是已经实现了循环跳转,只是我们肉眼难以察觉。注意,设置偏移量时animate要设置为NO。同理,当向左滑动xOff为0时,继续滑动,我们想要看到的是第五张图片,索引为4。因此当xOff小于0时,设置设置UIScrollView的偏移量为CGPointMake(1600, 0),此时我们看到的仍然是第一张图片(第六张图片,索引5)。注意,在此处处理UIPageControl的选中页位置。

     1 - (void)scrollViewDidScroll:(UIScrollView *)scrollView{
     2     CGFloat xOff = scrollView.contentOffset.x;
     3     int index = xOff/kScreenWidth;
     4     
     5     if (index == 5) {
     6         _pageCtrl.currentPage = 0;
     7     }else{
     8         _pageCtrl.currentPage = index;
     9     }
    10     //    0      1      2      3       4       0
    11     // 0    320    640    960    1280    1600
    12     if (xOff > kScreenWidth * _imgArray.count) {
    13      
    14         [scrollView setContentOffset:CGPointMake(0, 0) animated:NO];
    15     
    16     }
    17     if (xOff < 0) {
    18         [scrollView setContentOffset:CGPointMake(kScreenWidth * _imgArray.count, 0) animated:NO];
    19     }
    20     
    21 }

    至此,轮播图的基本工功能,我们已经大致实现了。下面,我们添加一个定时器,使UIScrollView能够根据定时器每隔1s自动滚动:

          number = 0;
        _timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(setOffsetMethod) userInfo:nil repeats:YES];
    
    
    - (void)setOffsetMethod{
        
        number++;
        [_scrollView setContentOffset:CGPointMake(kScreenWidth * number, 0) animated:YES];
        
    }

    要注意当滚动到最后一个索引时,使number= 0;

    - (void)scrollViewDidScroll:(UIScrollView *)scrollView{
        CGFloat xOff = scrollView.contentOffset.x;
        int index = xOff/kScreenWidth;
        
        if (index == 5) {
            _pageCtrl.currentPage = 0;
        }else{
            _pageCtrl.currentPage = index;
        }
        //    0      1      2      3       4       0
        // 0    320    640    960    1280    1600
        if (xOff > kScreenWidth * _imgArray.count) {
            number = 0;
            [scrollView setContentOffset:CGPointMake(0, 0) animated:NO];
        
        }
        if (xOff < 0) {
            [scrollView setContentOffset:CGPointMake(kScreenWidth * _imgArray.count, 0) animated:NO];
        }
        
    }

    接下来有一个重要问题就是解决定时器与滑动手势的冲突,实现下面两个代理方法:

    //开始拖动
    - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{
        NSLog(@"开始拖动");
        [_timer setFireDate:[NSDate distantFuture]];
    }
    //结束拖动
    - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{
        NSLog(@"结束拖动");
        int index = scrollView.contentOffset.x/kScreenWidth;
        number = index;
        [_timer setFireDate:[NSDate date]];
    }

    下面是轮播图项目的全部代码:

      1 //  轮播图
      2 
      3 #import "Test02ViewController.h"
      4 #import "UIViewExt.h"
      5 #import "Test01ViewController.h"
      6 
      7 @interface Test02ViewController ()<UIScrollViewDelegate>
      8 {
      9     NSInteger number;
     10 }
     11 @property(nonatomic, strong)UIScrollView *scrollView;
     12 @property(nonatomic, strong)NSArray *imgArray;
     13 @property(nonatomic, strong)UIPageControl *pageCtrl;
     14 
     15 @property(nonatomic, strong)NSTimer *timer;
     16 
     17 @end
     18 
     19 @implementation Test02ViewController
     20 
     21 - (void)viewDidLoad {
     22     [super viewDidLoad];
     23     // Do any additional setup after loading the view.
     24     self.view.backgroundColor = [UIColor whiteColor];
     25     self.navigationController.navigationBar.translucent = NO;
     26     _imgArray = @[@"01.jpg", @"02.jpg", @"03.jpg", @"04.jpg", @"05.jpg"];
     27     [self addSubViews];
     28     NSLog(@"viewDidLoad");
     29 }
     30 
     31 - (void)viewWillAppear:(BOOL)animated{
     32     [super viewWillAppear:animated];
     33     [_scrollView setContentOffset:CGPointMake(0, 0) animated:NO];
     34 
     35 }
     36 - (void)viewDidAppear:(BOOL)animated{
     37     [super viewDidAppear:animated];
     38 
     39     number = 0;
     40     _timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(setOffsetMethod) userInfo:nil repeats:YES];
     41 }
     42 - (void)viewWillDisappear:(BOOL)animated{
     43     [super viewWillDisappear:animated];
     44     
     45     [_timer invalidate];
     46 }
     47 
     48 - (void)addSubViews{
     49     _scrollView = [[UIScrollView alloc]initWithFrame:CGRectMake(0, 0, kScreenWidth, 200)];
     50     _scrollView.contentSize = CGSizeMake(kScreenWidth * (_imgArray.count + 1), 200);
     51     _scrollView.pagingEnabled = YES;
     52     _scrollView.delegate = self;
     53     _scrollView.showsHorizontalScrollIndicator = NO;
     54     //创建子视图
     55     for (int i = 0; i < _imgArray.count + 1; i++) {
     56         UIImageView *imgView = [[UIImageView alloc]initWithFrame:CGRectMake(0 + i * kScreenWidth, 0, kScreenWidth, 200)];
     57         if (i == _imgArray.count) {
     58             imgView.image = [UIImage imageNamed:_imgArray[0]];
     59         }else{
     60           imgView.image = [UIImage imageNamed:_imgArray[i]];
     61         }
     62         UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]init];
     63         [tap addTarget:self action:@selector(touchAction)];
     64         [imgView addGestureRecognizer:tap];
     65         imgView.userInteractionEnabled = YES;
     66         
     67         [_scrollView addSubview:imgView];
     68     }
     69     [self.view addSubview:_scrollView];
     70     
     71     //创建分页控件
     72     _pageCtrl = [[UIPageControl alloc]initWithFrame:CGRectMake((kScreenWidth - 130)/2, _scrollView.bottom - 20, 130, 15)];
     73     //_pageCtrl.backgroundColor = [UIColor cyanColor];
     74     _pageCtrl.numberOfPages = _imgArray.count;
     75     _pageCtrl.currentPage = 0;
     76     [self.view addSubview:_pageCtrl];
     77     
     78 }
     79 - (void)touchAction{
     80     NSLog(@"点击");
     81     [_timer setFireDate:[NSDate distantFuture]];
     82     [self pushVC];
     83 }
     84 
     85 #pragma mark -UIScrollViewDelegate
     86 //已经滑动
     87 - (void)scrollViewDidScroll:(UIScrollView *)scrollView{
     88     CGFloat xOff = scrollView.contentOffset.x;
     89     int index = xOff/kScreenWidth;
     90     
     91     if (index == 5) {
     92         _pageCtrl.currentPage = 0;
     93     }else{
     94         _pageCtrl.currentPage = index;
     95     }
     96     //    0      1      2      3       4       0
     97     // 0    320    640    960    1280    1600
     98     if (xOff > kScreenWidth * _imgArray.count) {
     99         number = 0;
    100         [scrollView setContentOffset:CGPointMake(0, 0) animated:NO];
    101     
    102     }
    103     if (xOff < 0) {
    104         [scrollView setContentOffset:CGPointMake(kScreenWidth * _imgArray.count, 0) animated:NO];
    105     }
    106     
    107 }
    108 - (void)setOffsetMethod{
    109     
    110     number++;
    111     [_scrollView setContentOffset:CGPointMake(kScreenWidth * number, 0) animated:YES];
    112     
    113 }
    114 //开始拖动
    115 - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{
    116     NSLog(@"开始拖动");
    117     [_timer setFireDate:[NSDate distantFuture]];
    118 }
    119 //结束拖动
    120 - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{
    121     NSLog(@"结束拖动");
    122     int index = scrollView.contentOffset.x/kScreenWidth;
    123     number = index;
    124     [_timer setFireDate:[NSDate date]];
    125 }
    126 - (void)pushVC{
    127     Test01ViewController *test01VC = [[Test01ViewController alloc]init];
    128     [self.navigationController pushViewController:test01VC animated:YES];
    129 }
    130 
    131 
    132 
    133 - (void)didReceiveMemoryWarning {
    134     [super didReceiveMemoryWarning];
    135     // Dispose of any resources that can be recreated.
    136 }
    137 
    138 /*
    139 #pragma mark - Navigation
    140 
    141 // In a storyboard-based application, you will often want to do a little preparation before navigation
    142 - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    143     // Get the new view controller using [segue destinationViewController].
    144     // Pass the selected object to the new view controller.
    145 }
    146 */
    147 
    148 @end
    View Code
  • 相关阅读:
    使用相对路径名导入包中子模块
    python中子类使用父类属性
    快速掌握Java8 Stream函数式编程技巧
    灵感来袭,基于Redis的分布式延迟队列(续)
    寻找最长不含有重复字符的子串 示例
    golang学习笔记---函数示例
    golang学习笔记---逐行读取文件示例
    golang学习笔记---int转二进制示例
    golang学习笔记---iota(枚举自增值)
    golang学习笔记 ----container/list包用法
  • 原文地址:https://www.cnblogs.com/whongs/p/6702673.html
Copyright © 2020-2023  润新知