1、先上图
2、应用场景
2.1、多个视图需要循环播放,一般情况下有多少个视图创建个多少个View排列在ScrollView即可,但如果视图过多会直接影响到手机性能及切换效果。
2.2、视图个数不确定的场景,绝大多数情况下我们都采用的是MVC的标准设计模式,即视图由数据决定,但数据的变化没法事先确定,因此视图必须具备一定灵活性。
3、设计思想
3.1、创建基础ScrollView并添加三个子控件到ScrollView,为什么是三个呢?这个问题问得好,我们一般情况下展示第二个,往左切换到第一个,往右切换到第三个,切换完成后,通过一系列算法立即将当前视图切换到中间一个的位置,调整子视图相对位置,实现重复效果!
3.2、看如下示意图:
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