关闭

uiscrollview 无缝循环滚动

607人阅读 评论(0) 收藏 举报

最近开发一个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

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:68814次
    • 积分:627
    • 等级:
    • 排名:千里之外
    • 原创:5篇
    • 转载:22篇
    • 译文:0篇
    • 评论:8条
    文章分类
    最新评论