美文网首页
325,轮播图的实现原理

325,轮播图的实现原理

作者: 枫叶1234 | 来源:发表于2020-10-15 09:31 被阅读0次

    第一种:

    同学们在写需求的时候肯定会时常用到UIScrollView。而说到UIScrollView,大家最先想到的肯定就是它上面的无限轮播功能。苹果在UIScrollView上并没有提供相应的方法让大家实现轮播,所以就需要通过代码进行处理来实现。先上图

    无限轮播效果图.gif
    我先给大家讲讲其实现的原理:
    我们假设用几张图片实现轮播效果。首先,我们需要打开UIScrollView的分页滑动

    /// 分页滑动
    _scrollView.scrollEnabled = YES;

    它方便的帮助我们实现了轮播的效果,然后就需要我们来实现“无限的”轮播。接下来,我们就需要摆放图片了,在摆放图片时需要注意,我们需要在第一张图片的位置摆放最后一张图片(可能有点懵哈,不过不要着急慢慢往下看),然后我们依次摆放图片(从第一张到最后一张),最后在所有图片的尾部我们再放上第一张图片。这样我们就多放了两张图片(分别在首尾多放了一张图)。我把对应的方法写一下:

    /// 将图片放置在UIScrollView上
    -(void)setupImage {
        /// 在UIScrollView的最前面添加一张图片
        UIImageView *firstImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, kScreenWidth, self.scrollView.frame.size.height)];
        /// 图片名是最后一张图片
        firstImageView.image = [UIImage imageNamed:self.imageNameList.lastObject];
        [self.scrollView addSubview:firstImageView];
        
        /// 添加图片
        for (NSInteger index = 0; index < self.imageNameList.count; index ++) {
            /// UIScrollView上的每一张图片
            UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake((index + 1) * kScreenWidth, 0, kScreenWidth, self.scrollView.frame.size.height)];
            imageView.image = [UIImage imageNamed:self.imageNameList[index]];
            
            [self.scrollView addSubview:imageView];
            self.scrollView.contentSize = CGSizeMake((index + 2) * self.scrollView.bounds.size.width, 0);
        }
        
        /// 在UIScrollView的最后面添加一张图片
        UIImageView *lastImageView = [[UIImageView alloc] initWithFrame:CGRectMake((self.imageNameList.count + 1) * kScreenWidth, 0, kScreenWidth, self.scrollView.frame.size.height)];
        /// 图片名是第一张图片
        lastImageView.image = [UIImage imageNamed:self.imageNameList.firstObject];
        [self.scrollView addSubview:lastImageView];
        
        /// 设置UIScrollView的偏移量
        self.scrollView.contentSize = CGSizeMake((self.imageNameList.count + 2) * self.scrollView.bounds.size.width, 0);
        
        /// 设置UIScrollView的起始偏移距离(将第一张图片跳过)
        self.scrollView.contentOffset = CGPointMake(kScreenWidth, 0);
        
        /// 图片总数
        self.pageControl.numberOfPages = self.imageNameList.count;
        self.pageControl.currentPage = 0;
    }
    
    

    其实,如果大家看到这里,应该就会大致明白无线轮播的实现原理了。接下来就是最后一步,在UIScrollView的代理方法里面写逻辑:判断UIScrollView的偏移量,当其滑动到首位时(显示的是最后一张图片),滑动停止,就把偏移量修改最后面图片的位置上(倒数第二张)。同理,当UIScrollView滑动到最后时(显示的是第一张图片),滑动停止,就把偏移量修改到第一张图片的位置上(正数第二张)。

    #pragma mark - UIScrollViewDelegate
    -(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
        /// 当UIScrollView滑动到第一位停止时,将UIScrollView的偏移位置改变
        if (scrollView.contentOffset.x == 0) {
            scrollView.contentOffset = CGPointMake(self.imageNameList.count * kScreenWidth, 0);
            self.pageControl.currentPage = self.imageNameList.count;
        /// 当UIScrollView滑动到最后一位停止时,将UIScrollView的偏移位置改变
        } else if (scrollView.contentOffset.x == (self.imageNameList.count + 1)* kScreenWidth) {
            scrollView.contentOffset = CGPointMake(kScreenWidth, 0);
            self.pageControl.currentPage = 0;
        } else {
            self.pageControl.currentPage = scrollView.contentOffset.x / kScreenWidth - 1;
        }
    }
    
    

    ok,原理其实就是这样。在首尾多加两张图片当做占位符,然后当UIScrollView滑动到占位符的位置时,改变UIScrollView的偏移量,简单且方便。下面就是全部代码

    #import "ViewController.h"
     
    #define kScreenWidth [UIScreen mainScreen].bounds.size.width
     
    @interface ViewController () <UIScrollViewDelegate>
     
    /// 滑动控制器
    @property (nonatomic, strong) UIScrollView *scrollView;
    /// 图片数组
    @property (nonatomic, strong) NSArray<NSString *> *imageNameList;
    /// 页码控制器
    @property (nonatomic, strong) UIPageControl *pageControl;
     
    @end
     
    @implementation ViewController
     
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        // 设置图片名的数组
        self.imageNameList = @[@"image0", @"image1", @"image2", @"image3"];
        
        // 添加图片
        [self setupImage];
    }
     
    /// 将图片放置在UIScrollView上
    -(void)setupImage {
        /// 在UIScrollView的最前面添加一张图片
        UIImageView *firstImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, kScreenWidth, self.scrollView.frame.size.height)];
        /// 图片名是最后一张图片
        firstImageView.image = [UIImage imageNamed:self.imageNameList.lastObject];
        [self.scrollView addSubview:firstImageView];
        
        /// 添加图片
        for (NSInteger index = 0; index < self.imageNameList.count; index ++) {
            /// UIScrollView上的每一张图片
            UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake((index + 1) * kScreenWidth, 0, kScreenWidth, self.scrollView.frame.size.height)];
            imageView.image = [UIImage imageNamed:self.imageNameList[index]];
            
            [self.scrollView addSubview:imageView];
            self.scrollView.contentSize = CGSizeMake((index + 2) * self.scrollView.bounds.size.width, 0);
        }
        
        /// 在UIScrollView的最后面添加一张图片
        UIImageView *lastImageView = [[UIImageView alloc] initWithFrame:CGRectMake((self.imageNameList.count + 1) * kScreenWidth, 0, kScreenWidth, self.scrollView.frame.size.height)];
        /// 图片名是第一张图片
        lastImageView.image = [UIImage imageNamed:self.imageNameList.firstObject];
        [self.scrollView addSubview:lastImageView];
        
        /// 设置UIScrollView的偏移量
        self.scrollView.contentSize = CGSizeMake((self.imageNameList.count + 2) * self.scrollView.bounds.size.width, 0);
        
        /// 设置UIScrollView的起始偏移距离(将第一张图片跳过)
        self.scrollView.contentOffset = CGPointMake(kScreenWidth, 0);
        
        /// 图片总数
        self.pageControl.numberOfPages = self.imageNameList.count;
        self.pageControl.currentPage = 0;
    }
     
    #pragma mark - UIScrollViewDelegate
    -(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
        /// 当UIScrollView滑动到第一位停止时,将UIScrollView的偏移位置改变
        if (scrollView.contentOffset.x == 0) {
            scrollView.contentOffset = CGPointMake(self.imageNameList.count * kScreenWidth, 0);
            self.pageControl.currentPage = self.imageNameList.count;
        /// 当UIScrollView滑动到最后一位停止时,将UIScrollView的偏移位置改变
        } else if (scrollView.contentOffset.x == (self.imageNameList.count + 1)* kScreenWidth) {
            scrollView.contentOffset = CGPointMake(kScreenWidth, 0);
            self.pageControl.currentPage = 0;
        } else {
            self.pageControl.currentPage = scrollView.contentOffset.x / kScreenWidth - 1;
        }
    }
     
    #pragma mark - Get方法
    -(UIScrollView *)scrollView {
        if (!_scrollView) {
            _scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, kScreenWidth, 200)];
            _scrollView.pagingEnabled = YES;
            _scrollView.clipsToBounds = NO;
            _scrollView.scrollEnabled = YES;
            _scrollView.delegate = self;
            _scrollView.bounces = NO;
            _scrollView.showsHorizontalScrollIndicator = NO;
            _scrollView.showsVerticalScrollIndicator = NO;
            
            [self.view addSubview:_scrollView];
        }
        
        return _scrollView;
    }
     
    -(UIPageControl *)pageControl {
        if (!_pageControl) {
            _pageControl = [[UIPageControl alloc] initWithFrame:CGRectMake(0, 150, kScreenWidth, 50)];
            
            _pageControl.pageIndicatorTintColor = [UIColor blackColor];
            _pageControl.currentPageIndicatorTintColor = [UIColor grayColor];
            
            [self.view addSubview:_pageControl];
        }
        
        return _pageControl;
    }
     
    @end
    
    

    第二种 用3个ImageView来实现

    实现原理:
    比如有5张图片,创建三个imageView,分别展示图片5,图片1,图片2,默认展示第二张(图片1),向右滑动显示第3张(图片2),显示完成后,将scrollView的contentOffset重新设置到中间图片,并根据引用计数+1,重新刷新图片,三个imageView分别展示为,图片1,图片2,图片3,这时候就相当于图片2在中间,图片3在右边。同理再次向右滑动,显示图片第3张(图片3),显示完成后,再将scrollView的contentOffset重新设置到中间图片上面,并根据引用计数+1,重新刷新图片,三个imageView分别展示为图片2,图片3,图片4,这时候就相当于图片3在中间,图片4在右边,依次下去,便可实现无限循环。

    第三种 collectionView来实现

    二、原理说明

    通过UICollectionView实现横向滚动轮播效果如下图所示,当移动到左右边缘后不可以继续移动

    将CollectionView展开后的示意图如下:

    思考:要使CollectionView滚动到左边缘和右边缘时均可以继续滚动,并且从左边缘向左滚动时显示的是最后一页,从右边缘向右滚动时显示的是第一页,可以在左边插入最后一页,在右边插入第一页,这样就可以滚动了。

    示意图如下:

    运行效果

    现在还差最后一步了,当手动滚动到左侧第一页时,让CollectionView自动滚动到倒数第二页:

    运行效果如下:

    当手动滚动到最后一页时,让CollectionView自动滚动到正数第二页:

    相关文章

      网友评论

          本文标题:325,轮播图的实现原理

          本文链接:https://www.haomeiwen.com/subject/cukipktx.html