65

iOS 实现UIScrollView的无限轮播(原理)

 5 years ago
source link: http://www.cocoachina.com/ios/20180928/25057.html?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

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

jMV3MzR.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

好了,如果大家使用的是swift语言,还可以参考这篇文章: https://www.jianshu.com/p/0ba33e59a784

作者:枫developer

链接:https://www.jianshu.com/p/7c4b79e5b123


Recommend

  • 59
    • fed.renren.com 6 years ago
    • Cache

    Vue实现内部组件轮播切换效果

    Vue实现内部组件轮播切换效果

  • 64

    实现思路1将文本和图片拼接为HTML代码。2使用JavaScript添加点击事件。3使用MagicWebViewWebP提供UIWebView加载webp格式图片支持。4使用UIWebView加载HTML代码。5使用UIWebView代理方法,拦截页面发出的请求,获取selectIndex。

  • 55
    • www.cocoachina.com 5 years ago
    • Cache

    iOS 多级 UIScrollView 嵌套的实现方案

    本文实现了一种多级 UIScrollView 嵌套的交互,主要解决事件传递和手势冲突问题。

  • 21
    • www.cnblogs.com 3 years ago
    • Cache

    Android实现轮播图

    首先总结一下大体思路就是通过一个ViewPager来进行无限的自动滑动来达到我们想要的实现的轮播图效果 首先先写UI <?xml version="1.0" encoding="utf-8"?> <LinearLayout android:orientation="vertical"...

  • 14

    去年8月份,我在Github开源了一个无限循环的轮播图库— BannerViewPager (以下简称BVP)。时至今日,一年多的时间过去了,BVP在大家的支持下已经在GitHub上收获了1.9k的Star。...

  • 9

    iOS下自己动手造无限循环图片轮播 浏览:798次  出处信息    代码示...

  • 1
    • segmentfault.com 2 years ago
    • Cache

    运用CSS实现轮播图

    运用CSS实现轮播图发布于 33 分钟前<!-- * @Author: [you name] * @Date: 2021-09-16 23:22:37 * @LastEditors: [you name] * @LastEditTime: 2021-09-16...

  • 6
    • www.scarsu.com 2 years ago
    • Cache

    前端 | 纯CSS实现无限循环轮播

    前端 | 纯CSS实现无限循环轮播无JS代码实现无限循环轮播、鼠标悬浮时暂停动画、鼠标移出时继续动画2022-04-22 | 10技术 | 前端 | 156 字 | 1 分钟 | 阅读量 20

  • 3

    轮播图经常会在项目里用到,但是实际上用到的轮播图都是比较简单的,没有复杂的特效,这个时候如果去引入swiper那些库的话,未免就有点杀鸡焉用牛刀了。 所以不如自己手写一个,而今天我要分享的一种写法也是我最近才发现的,发现写起来真的是很丝滑,只纯css...

  • 4
    • scarsu.com 9 months ago
    • Cache

    纯CSS实现无限循环轮播

    纯CSS实现无限循环轮播无JS代码实现无限循环轮播、鼠标悬浮时暂停动画、鼠标移出时继续动画 2022/4/23 1...

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK