轻松实现UIScrollView循环滚动

1、先上图

未命名-1

2、应用场景

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

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

3、设计思想

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

3.2、看如下示意图:

000

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、示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
//
//? ViewController.m
//? Test
//
//? Created by 余西安 on 15/7/1.
//? Copyright (c) 2015年 Sian. All rights reserved.
//
?
#import "ViewController.h"
?
@interface ViewController () 
@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下载 ScrollView

Leave a Reply