• iOS完美版的UIScrollView无缝循环:你值得一看


    • 可以直接copy运行研究

    • .m头文件和声明的常量(宏和const)

    #import "ViewController.h"

    // UIScrollView的尺寸

    const CGFloat WSCROLL = 300;

    const CGFloat HSCROLL = 200;

    #define VWSCROLL (self.view.frame.size.width-WSCROLL)/2

    #define VHSCROLL self.view.frame.size.height/7

    // 图片的数量

    #define COUNTImage 6


    •  所有的属性都封装在延展内:保证了封装性,只是给外界提供了数据传输接口,图片的显示和数据源是分开的,因此只是本类使用到的文件可以写在延展内

    @interface ViewController ()

    // 视图

    @property (nonatomic, strong)UIScrollView *scrol;

    // 翻页

    @property (nonatomic, strong)UIPageControl *page;

    // 固定三个视图:每次都显示中间(偏移量为当前UIScrollView的宽度:数组索引为1)

    @property (nonatomic, strong)UIImageView *imv_1;

    @property (nonatomic, strong)UIImageView *imv_2;

    @property (nonatomic, strong)UIImageView *imv_3;

    // 数据源:让显示和数据分开

    @property (nonatomic, strong)NSMutableArray *arrImages;

    // 记录偏移量:判断偏移后显示的图片,即数组的下标

    @property (nonatomic, assign)NSInteger currentPage;

    @end


    • 具体实现和注释已经很清晰了,多看

    /**

     *  通过偏移量,只是改变了数组的下标(换图),view还是居中

     */

    @implementation ViewController

    - (void)viewDidLoad

    {

        [super viewDidLoad];

        // 1.获取数据源:让显示和数据隔离

        self.arrImages = [NSMutableArray array];

        for (int i = 0; i < COUNTImage; i++)

        {

            [self.arrImages addObject:[NSString stringWithFormat:@"bailidujuan%i.jpg", i]];

        }

        

        // 2.创建UIScrollView

        self.scrol = [[UIScrollView alloc] initWithFrame:CGRectMake(VWSCROLL, VHSCROLL, WSCROLL, HSCROLL)];

        // - 只是通过偏移量还更换数组内图片,3个视图保证了往左或者往右都会偏移量:减少内存占用

        self.scrol.contentSize = CGSizeMake(WSCROLL*3, HSCROLL);

        // - 允许分页

        self.scrol.pagingEnabled = YES;

        // - 隐藏滚动条

        self.scrol.showsHorizontalScrollIndicator = NO;

        // - 去掉回弹效果

        self.scrol.bounces = NO;

        // - 创建视图:因为只有三个视图,因此偏移量是两个定值:只是初始化对象

        self.imv_1 = [[UIImageView alloc] init];

        self.imv_2 = [[UIImageView alloc] init];

        self.imv_3 = [[UIImageView alloc] init];

        

        // 3.添加分页标识

        self.page = [[UIPageControl alloc] initWithFrame:CGRectMake((self.view.frame.size.width-100)/2, WSCROLL-30, 100, 30)];

        // - 确定页数

        self.page.numberOfPages = COUNTImage;

        // - 清除背景色

        //self.page.backgroundColor = [UIColor clearColor];

        // - 更换分页颜色

        self.page.currentPageIndicatorTintColor = [UIColor purpleColor];

        self.page.pageIndicatorTintColor = [UIColor whiteColor]; //切换页

        // - 和用户不交互

        self.page.userInteractionEnabled = NO;

        

        // - 传递页数需要代理实现

        self.scrol.delegate = self;

        // - 当前页码

        self.currentPage = 0;

        // - 默认加载第一张图

        [self reloadImage];

        

        // - 添加到视图:先添加UIScrollView再添加UIPageControl,避免分页被覆盖

        [self.view addSubview:self.scrol];

        [self.view addSubview:self.page];

        

        

    }


    • 自定义方法只是通过传递下标确定显示的图片

    -(void)reloadImage

    {

        // 根据下标显示图片:每次都显示中间(偏移量为当前UIScrollView的宽度:数组索引三种情况)

        // 每次只是在显示对应索引以及它前后的图片:索引的获取需要偏移量contentOffset

        

        // 第一页:

        if (!_currentPage)

        {

            self.imv_1.image = [UIImage imageNamed:[self.arrImages lastObject]];

            self.imv_2.image = [UIImage imageNamed:self.arrImages[self.currentPage]];

            self.imv_3.image = [UIImage imageNamed:self.arrImages[self.currentPage+1]];

        }

        // 最后一页

        else if (_currentPage == COUNTImage -1)

        {

            self.imv_1.image = [UIImage imageNamed:self.arrImages[self.currentPage-1]];

            self.imv_2.image = [UIImage imageNamed:self.arrImages[self.currentPage]];

            self.imv_3.image = [UIImage imageNamed:[self.arrImages firstObject]];

        }

        // 中间页

        else

        {

            self.imv_1.image = [UIImage imageNamed:self.arrImages[self.currentPage-1]];

            self.imv_2.image = [UIImage imageNamed:self.arrImages[self.currentPage]];

            self.imv_3.image = [UIImage imageNamed:self.arrImages[self.currentPage+1]];

        }

        

        // 每次修改frame:显示数据不为空再给frame赋值

        self.imv_1.frame = CGRectMake(0, 0, WSCROLL, HSCROLL);

        self.imv_2.frame = CGRectMake(WSCROLL, 0, WSCROLL, HSCROLL);

        self.imv_3.frame = CGRectMake(WSCROLL*2, 0, WSCROLL, HSCROLL);

        

        [self.scrol addSubview:self.imv_1];

        [self.scrol addSubview:self.imv_2];

        [self.scrol addSubview:self.imv_3];

        

        // 让每次切换都能看到三张图:保证流畅性(每次显示的都是中间一张图)

        self.scrol.contentOffset = CGPointMake(WSCROLL, 0);

    }


    • 确定下标的过程

    #pragma mark - ScrollView Delegate

    //在滚动结束状态换图:DidEnd

    - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {

       

        // 确定下标:通过判断偏移量改变索引

        // 因为只有三个视图,因此偏移量是两个定值

       

        // 向左:偏移量恒为0

        if (!self.scrol.contentOffset.x)

        {

            if (!_currentPage)

            {

                // 在第0页左移后,集合索引为最后一个对象:

                _currentPage = COUNTImage - 1; // self.arrImages.count - 1 = COUNTImage - 1

            }

            else

            {

                _currentPage--; // 一直左移,只会走一次if语句直到0

            }

        }

        

        // 向右:偏移量恒为两倍

        if (self.scrol.contentOffset.x == WSCROLL*2)

        {

            if (_currentPage == COUNTImage - 1)

            {

                _currentPage = 0; // 在最后一页右移:集合索引就赋值为0

            }

            else

            {

                // 一直右移,只会在到达最后一个元素位置走if语句

                _currentPage++;

            }

        }

        

        // 页数即为集合的下标

        self.page.currentPage = _currentPage;

        // 对应方法显示下标对应的图片

        [self reloadImage];

    }


    • Xcode自带程序

    #pragma mark -

    - (void)didReceiveMemoryWarning

    {

        [super didReceiveMemoryWarning];

        // Dispose of any resources that can be recreated.

    }

    @end


    初学者整理,思路可能很简单,希望大家可以相互学习 

  • 相关阅读:
    ES6--Promise讲解
    JavaScript原型链以及Object,Function之间的关系
    webpack中利用require.ensure()实现按需加载
    js中cssText批量修改元素样式
    js判断数组中是否有重复元素
    vue生命周期小总结
    学习vue生命周期
    [异步请求]ajax、axios、fetch之间的详细区别以及优缺点
    [Es6]原生Promise的使用方法
    [javascript]原生js实现Ajax
  • 原文地址:https://www.cnblogs.com/pruple/p/5270357.html
Copyright © 2020-2023  润新知