uiscrollview 无缝循环滚动

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
 
@class ArticleViewController;
 
@interface ArticleScrollViewController : 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"
@implementation ArticleScrollViewController
 
// vieDidLoad函数不重要,只要初始化了三个view并放在uiscrollview里面,正确设定uiscrollview的content size就行了
- ( void )viewDidLoad {
     [ super viewDidLoad ];
 
     UIScrollView *scrollView = ( UIScrollView *) self .view;
     scrollView.contentSize = CGSizeMake ( self .view.frame.size.width *3 , self .view.frame.size.height);
     CGRect frame = self .view.frame;
     frame.origin.y = 0 .0f ;
     NSInteger article2Index = [ViewSwitcher getInstance ].currentArticleIndex;
     NSInteger article1Index = article2Index - 1 ;
     article1Index = article1Index < 0 ? [ViewSwitcher getInstance ].articleCount - 1 : article1Index;
     article1Index = article1Index >= [ViewSwitcher getInstance ].articleCount ? 0 : article1Index;
     NSInteger article3Index = article2Index + 1 ;
     article3Index = article3Index < 0 ? [ViewSwitcher getInstance ].articleCount - 1 : article3Index;
     article3Index = article3Index >= [ViewSwitcher getInstance ].articleCount ? 0 : article3Index;
 
     article1 = [[ArticleViewController alloc ] initWithArticleIndex :article1Index];
     [article1.view setFrame :frame];
 
     article2 = [[ArticleViewController alloc ] initWithArticleIndex :article2Index];
     frame.origin.x += self .view.frame.size.width;
     [article2.view setFrame :frame];
 
     article3 = [[ArticleViewController alloc ] initWithArticleIndex :article3Index];
     frame.origin.x += self .view.frame.size.width;
     [article3.view setFrame :frame];
 
     [scrollView addSubview :article1.view];
     [scrollView addSubview :article2.view];
     [scrollView addSubview :article3.view];
 
     CGPoint p = CGPointZero ;
     p.x = scrollView.frame.size.width;
     [scrollView setContentOffset :p animated : NO ];
     [article2 reloadData ];
}
#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.view setFrame : 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 ;
     }
     [article1 reloadData ];
     ArticleViewController *tmpArticleViewController = article3;
     article3 = article2;
     article2 = article1;
     article1 = tmpArticleViewController;
 
     float increase = pageWidth;
     CGFloat x = 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 ;
     }
     [article3 reloadData ]; //[article2 resetView];[article3 resetView];
     ArticleViewController *tmpArticleViewController = article1;
     article1 = article2;
     article2 = article3;
     article3 = tmpArticleViewController;
 
     float increase = -pageWidth;
     CGFloat x = 0 .0f ;
     SET_FRAME(article2);
     SET_FRAME(article3);
     SET_FRAME(article1);
}
/*
  循环滚动
  每次滚动后都将scrollview的offset设置为中间的一页
  若本次滚动是向前一页滚动,则把三页都向后放置,最后一页放到开头
  若本次滚动是向后一页滚动,则把三页都向前放置,第一页放到末尾
  */
- ( void )scrollViewDidEndDecelerating:( UIScrollView *)theScrollView
{
     CGFloat pageWidth = theScrollView.frame.size.width;
     // 0 1 2
     int page = floor((theScrollView.contentOffset.x - pageWidth / 2 ) / pageWidth) + 1 ;
     if (page == 1 ) {
         //用户拖动了,但是滚动事件没有生效
         return ;
     } else if (page == 0 ) {
         [ self allArticlesMoveRight :pageWidth];
     } else {
         [ self allArticlesMoveLeft :pageWidth];
     }
     CGPoint p = CGPointZero ;
     p.x = pageWidth;
     [theScrollView setContentOffset :p animated : NO ];
     [article1 resetView ];
     [article3 resetView ];
}
#pragma mark -
#pragma mark dealloc
- ( void )didReceiveMemoryWarning {
     // Releases the view if it doesn't have a superview.
     [ super didReceiveMemoryWarning ];
 
     // Release any cached data, images, etc. that aren't in use.
}
 
- ( void )viewDidUnload {
     [ super viewDidUnload ];
     // 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];
     [ super dealloc ];
}
 
@end

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

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

article1 article2 article3
          【屏幕】

拖动以后成这样:

article1 article2 article3
【屏幕】

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

article3 article1 article2
【屏幕】

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

article3 article1 article2
          【屏幕】

最后更新指针顺序:

article1 article2 article3
          【屏幕】

无缝循环实现了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值