年年有"余"

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 3195|回复: 0

轻松实现UIScrollView循环滚动

[复制链接]
  • TA的每日心情
    奋斗
    2022-12-13 21:26
  • 签到天数: 371 天

    [LV.9]以坛为家II

    发表于 2015-7-1 15:03:23 | 显示全部楼层 |阅读模式
    本帖最后由 Sian 于 2015-7-1 15:29 编辑

    1、先上图

    未命名~1.gif

    2、应用场景

    2.1、多个视图需要循环播放,一般情况下有多少个视图创建个多少个View排列在ScrollView即可,但如果视图过多会直接影响到手机性能及切换效果。

    2.2、视图个数不确定的场景,绝大多数情况下我们都采用的是MVC的标准设计模式,即视图由数据决定,但数据的变化没法事先确定,因此视图必须具备一定灵活性。

    3、设计思想

    3.1、创建基础ScrollView并添加三个子控件到ScrollView,为什么是三个呢?这个问题问得好,我们一般情况下展示第二个,往左切换到第一个,往右切换到第三个,切换完成后,通过一系列算法立即将当前视图切换到中间一个的位置,调整子视图相对位置,实现重复效果!

    3.2、看如下示意图:

    000.png

    3.3、首先将子控件的tag进行编号,如1、2、3(尽量不要用0,因为不排队有其他子控件的影响,view默认tag为0),通过tag决定位置,如:tag为1的子控件,x为width * 0,tag为1的子控件x为width * 1,tag为2的子控件x为width * 2,宽度高度相等,y默认都为0。

    3.4、有了上面这个前提就方便了,我们调整子控件即转换为调整子控件的tag值即可,然后再通过tag值重新计算子控件的位置就能实现需要的效果。

    3.5、有点抽象?看代码!

    4、示例代码
    [Objective-C] 纯文本查看 复制代码
    //
    //  ViewController.m
    //  Test
    //
    //  Created by 余西安 on 15/7/1.
    //  Copyright (c) 2015年 Sian. All rights reserved.
    //
    
    #import "ViewController.h"
    
    @interface ViewController () <UIScrollViewDelegate>
    @property (nonatomic, assign) BOOL         firstAppear;
    @property (nonatomic, strong) UIScrollView *scrollView;
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        self.firstAppear = YES;
        // 创建基础ScrollView控件
        UIScrollView *scrollView = [[UIScrollView alloc] init];
        scrollView.pagingEnabled = YES;
        scrollView.delegate = self;
    
        // 创建三个子控件并添加到ScrollView(子控件可以是UIView的任何子类,常用的如:UIImageView、UIWebView、UITextView等)
        for (int i = 0; i < 3; i++) {
            UILabel *label = [[UILabel alloc] init];
            label.tag = i + 1;
            label.textAlignment = NSTextAlignmentCenter;
            label.text = [NSString stringWithFormat:@"%ld", label.tag];
            label.font = [UIFont systemFontOfSize:160];
            [scrollView addSubview:label];
        }
        self.scrollView = scrollView;
        [self.view addSubview:scrollView];
    }
    
    - (void)viewWillAppear:(BOOL)animated
    {
        [super viewWillAppear:animated];
        if (self.firstAppear){
            [self viewFirstAppear:animated];
        }
    }
    
    - (void)viewDidAppear:(BOOL)animated
    {
        [super viewDidAppear:animated];
        self.firstAppear = NO;
    }
    
    /// 第一次出现该View时调整所有控件位置尺寸
    - (void)viewFirstAppear:(BOOL)aninated
    {
        self.scrollView.frame = self.view.bounds;
        CGSize size = self.view.bounds.size;
        for (UIView *view in self.scrollView.subviews) {
            NSInteger index = view.tag - 1;
            // 过滤掉scrollView原有的子控件
            if (index < 0) continue;
            CGFloat x = index * size.width;
            view.frame = (CGRect){x, 0, size};
        }
        self.scrollView.contentOffset = CGPointMake(size.width, 0);
        self.scrollView.contentSize = CGSizeMake(size.width * 3, size.height);
    }
    
    /// scrollView停止减速时调用,核心算法在这里!!
    - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
    {
        CGFloat width = scrollView.bounds.size.width;
        CGFloat offsetX = scrollView.contentOffset.x;
        NSInteger index = offsetX / width;
        // 让scrollView再次返回到最中间位置
        scrollView.contentOffset = CGPointMake(width, 0);
        // index取值为0、1、2分别对应当前为第几个视图
        switch (index){
            case 0:{    // 往左侧滑(手势往左),所有控件往左移一个单位,出界补最右边
                for (UIView *view in self.scrollView.subviews) {
                    if (view.tag < 1) continue; // 过滤
                    // 利用tag来决定位置(1、2、3)-> (2、3、1)
                    view.tag = (view.tag  % 3) + 1;
                    CGFloat x = (view.tag - 0.5) * width;
                    CGFloat y = view.center.y;
                    view.center = CGPointMake(x, y);
                }
            }break;
                
            case 2:{    // 往右侧滑(手势往右),所有控件往右移一个单位,出界补最左边
                for (UIView *view in self.scrollView.subviews) {
                    if (view.tag < 1) continue;
                    // 利用tag来决定位置(1、2、3)-> (3、1、2)
                    view.tag = ((view.tag  + 1) % 3) + 1;
                    CGFloat x = (view.tag - 0.5) * width;
                    CGFloat y = view.center.y;
                    view.center = CGPointMake(x, y);
                }
            }break;
            default:break;
        }
    }
    
    @end

    5、Demo下载
    游客,如果您要查看本帖隐藏内容请回复

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    手机版|小黑屋|Archiver|iOS开发笔记 ( 湘ICP备14010846号 )

    GMT+8, 2024-3-28 16:19 , Processed in 0.053160 second(s), 21 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表