您的位置:首页 > 产品设计 > UI/UE

UIScrollview 无缝循环滚动实现

2012-05-03 10:54 423 查看
头文件:

#import

@class ArticleViewController;

@interface ArticleScrollViewController : UIViewController  {
//不使用数组,看起来更明了,为了节省内存同时还要看起来无缝,3个view最好
ArticleViewController	*article1;
ArticleViewController	*article2;
ArticleViewController	*article3;
}

@end

实现:

#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
【屏幕】

无缝循环实现了。

by gqzhu

http://www.dreamingwish.com/dream-2011/uiscrollview-infinite-loop-scrolling.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: