uiscrollview 无缝循环滚动

来源:互联网 发布:赵薇 证监会 知乎 编辑:程序博客网 时间:2024/04/30 07:44

2011-11-05. 我终于闲下来,写了一个Demo,打包,欢迎大家下载

  InfiniteScroll.zip (18.1 KB, 126 次)

最近开发一个ipad/iphone应用,要用到无缝循环滚动,网上搜了一下uiscrollview循环滚动,都是那么一个帖子转来转去,循环的时候其实没法无缝,只好自己实现一个。

头文件:

1
2
3
4
5
6
7
8
9
10
11
12
#import
 
@classArticleViewController;
 
@interfaceArticleScrollViewController :UIViewController {
        //不使用数组,看起来更明了,为了节省内存同时还要看起来无缝,3个view最好
    ArticleViewController   *article1;
    ArticleViewController   *article2;
    ArticleViewController   *article3;
}
 
@end

实现:

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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#import "ArticleScrollViewController.h"
#import "ArticleViewController.h"
#import "ViewSwitcher.h"
@implementationArticleScrollViewController
 
// vieDidLoad函数不重要,只要初始化了三个view并放在uiscrollview里面,正确设定uiscrollview的content size就行了
- (void)viewDidLoad {
    [superviewDidLoad];
 
    UIScrollView*scrollView = (UIScrollView*)self.view;
    scrollView.contentSize = CGSizeMake(self.view.frame.size.width*3,self.view.frame.size.height);
    CGRectframe = self.view.frame;
    frame.origin.y = 0.0f;
    NSIntegerarticle2Index = [ViewSwitcher getInstance].currentArticleIndex;
    NSIntegerarticle1Index = article2Index - 1;
    article1Index = article1Index < 0 ? [ViewSwitcher getInstance].articleCount - 1 : article1Index;
    article1Index = article1Index >= [ViewSwitcher getInstance].articleCount ? 0 : article1Index;
    NSIntegerarticle3Index = article2Index + 1;
    article3Index = article3Index < 0 ? [ViewSwitcher getInstance].articleCount - 1 : article3Index;
    article3Index = article3Index >= [ViewSwitcher getInstance].articleCount ? 0 : article3Index;
 
    article1 = [[ArticleViewController alloc]initWithArticleIndex:article1Index];
    [article1.viewsetFrame:frame];
 
    article2 = [[ArticleViewController alloc]initWithArticleIndex:article2Index];
    frame.origin.x += self.view.frame.size.width;
    [article2.viewsetFrame:frame];
 
    article3 = [[ArticleViewController alloc]initWithArticleIndex:article3Index];
    frame.origin.x += self.view.frame.size.width;
    [article3.viewsetFrame:frame];
 
    [scrollViewaddSubview:article1.view];
    [scrollViewaddSubview:article2.view];
    [scrollViewaddSubview:article3.view];
 
    CGPointp = CGPointZero;
    p.x = scrollView.frame.size.width;
    [scrollViewsetContentOffset:panimated:NO];
    [article2reloadData];
}
#pragma mark -
#pragma mark UIScrollViewDelegate
 
#define SET_FRAME(ARTICLEX) x = ARTICLEX.view.frame.origin.x + increase;\
                            if(x < 0) x = pageWidth * 2;\
                            if(x > pageWidth * 2) x = 0.0f;\
                            [ARTICLEX.viewsetFrame:CGRectMake(x, \
                                ARTICLEX.view.frame.origin.y,\
                                ARTICLEX.view.frame.size.width,\
                                ARTICLEX.view.frame.size.height)]
//将三个view都向右移动,并更新三个指针的指向,article2永远指向当前显示的view,article1是左边的,article3是右边的
- (void)allArticlesMoveRight:(CGFloat)pageWidth {
    //上一篇
    article3.articleIndex = article1.articleIndex - 1;
    if(article3.articleIndex < 0) {
        article3.articleIndex = [ViewSwitcher getInstance].articleCount - 1;
    }
    [article1reloadData];
    ArticleViewController *tmpArticleViewController = article3;
    article3 = article2;
    article2 = article1;
    article1 = tmpArticleViewController;
 
    floatincrease = pageWidth;
    CGFloatx = 0.0f;
    SET_FRAME(article3);
    SET_FRAME(article1);
    SET_FRAME(article2);
}
- (void)allArticlesMoveLeft:(CGFloat)pageWidth {
    article1.articleIndex = article3.articleIndex + 1;
    if(article1.articleIndex >= [ViewSwitcher getInstance].articleCount) {
        article1.articleIndex = 0;
    }
    [article3reloadData];//[article2 resetView];[article3 resetView];
    ArticleViewController *tmpArticleViewController = article1;
    article1 = article2;
    article2 = article3;
    article3 = tmpArticleViewController;
 
    floatincrease = -pageWidth;
    CGFloatx = 0.0f;
    SET_FRAME(article2);
    SET_FRAME(article3);
    SET_FRAME(article1);
}
/*
 循环滚动
 每次滚动后都将scrollview的offset设置为中间的一页
 若本次滚动是向前一页滚动,则把三页都向后放置,最后一页放到开头
 若本次滚动是向后一页滚动,则把三页都向前放置,第一页放到末尾
 */
- (void)scrollViewDidEndDecelerating:(UIScrollView*)theScrollView
{
    CGFloatpageWidth = theScrollView.frame.size.width;
    // 0 1 2
    intpage = floor((theScrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
    if(page == 1) {
        //用户拖动了,但是滚动事件没有生效
        return;
    }elseif (page == 0) {
        [selfallArticlesMoveRight:pageWidth];
    }else{
        [selfallArticlesMoveLeft:pageWidth];
    }
    CGPointp = CGPointZero;
    p.x = pageWidth;
    [theScrollViewsetContentOffset:panimated:NO];
    [article1resetView];
    [article3resetView];
}
#pragma mark -
#pragma mark dealloc
- (void)didReceiveMemoryWarning {
    // Releases the view if it doesn't have a superview.
    [superdidReceiveMemoryWarning];
 
    // Release any cached data, images, etc. that aren't in use.
}
 
- (void)viewDidUnload {
    [superviewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
    [article1    release];article1 = nil;
    [article2    release];article2 = nil;
    [article3    release];article3 = nil;
}
 
- (void)dealloc {
    [article1    release];
    [article2    release];
    [article3    release];
    [superdealloc];
}
 
@end

这里的雕虫小技主要在于:

以手指向右拖动为例,【屏幕】指的是scorllview的显示区域

article1 article2 article3          【屏幕】

拖动以后成这样:

article1 article2 article3【屏幕】

将article3放到第一个去(设定article3的frame),这是屏幕还显示的是article1的内容

article3 article1 article2【屏幕】

将屏幕移到中间:使用setContentOffset,禁用动画,这样骗过人眼

article3 article1 article2          【屏幕】

最后更新指针顺序:

article1 article2 article3          【屏幕】

无缝循环实现了。

原创粉丝点击