IOS实现自动循环滚动广告--ScrollView的优化和封装

时间:2021-09-08 17:56:37

m

一、问题分析

  在许多App中,我们都会见到循环滚动的视图,比如广告,其实想实现这个功能并不难,用ScrollView就可以轻松完成,但是在制作的过程中还存在几个小问题,如果能够正确的处理好这些小问题,无论从效果还是性能上都会得到优化。

问题一

  第一个问题是如何用ScrollView来展示N个视图。想要实现这个效果,可以把N个视图依次按顺序添加到ScrollView上,然后把 ScrollView的contentSize设置为N个视图的尺寸,通过滑动ScrollView来查看加在上面的视图。

问题二

  第二个问题是如何完成图片的循环滚动,也就是展示完最后一张之后会接着展示第一张,形成图片的循环展示。想要实现这个效果,首先需要让ScrollView实现自动分页,这样可以保证滑动结束展示的是完整的视图;其次,需要根据当前展示的页数来设置ScrollView的contentOffset。

  对于第一个问题的解决是用的最简单的方式,但实际上忽略了一个很重要的问题,那就是如果要展示的视图数量N非常大的时候,我们该如何做呢?假设通过ScrollView来展示的每个视图的宽度恰好是屏幕的宽度,那么在展示的时候,其实能够呈现在我们眼前的最多只有两个视图,也就是要么是完整的一个视图,要么是两个不完整的视图。因此,我们只需要有三个视图,就能够完成循环的展示。

问题三

  第三个问题是在循环滚动的过程中,希望知道当前的页数,这个页数可以通过contentOffset.x来计算,通常会用UIPageControl来表示。此外,当点击某一个视图的时候,要能够知道当前点击的视图是哪一个。

问题四

  第四个问题是自动展示下一页的功能,这个需要写好跳到下一页的方法,然后通过NSTimer定时器来完成。

  除了上面的几个问题,大家也可以为其添加更多的功能。那么对于ScrollView自动翻页这样通用的功能,最好的方式是将其封装起来,这样可以大大的提高效率。下面的代码是把UIScrollView、UIPageControl封装到了一个UIView中,而其中的ScrollView用来循环展示多张图片。

二、功能实现

1、封装Scrollview代码.h:

?
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
//  WHScrollAndPageView.h
//  循环滚动视图
//
//  Created by jereh on 15-3-15.
//  Copyright (c) 2015年 jereh. All rights reserved.
//
 
# import <uikit uikit.h= "" >
 
@protocol WHcrollViewViewDelegate;
 
@interface WHScrollAndPageView : UIView <uiscrollviewdelegate>
{
     __unsafe_unretained id <whcrollviewviewdelegate> _delegate;
}
 
@property (nonatomic, assign) id <whcrollviewviewdelegate> delegate;
 
@property (nonatomic, assign) NSInteger currentPage;
 
@property (nonatomic, strong) NSMutableArray *imageViewAry;
 
@property (nonatomic, readonly) UIScrollView *scrollView;
 
@property (nonatomic, readonly) UIPageControl *pageControl;
 
-( void )shouldAutoShow:(BOOL)shouldStart;
 
@end
 
@protocol WHcrollViewViewDelegate <nsobject>
 
@optional
- ( void )didClickPage:(WHScrollAndPageView *)view atIndex:(NSInteger)index;
 
@end </nsobject></whcrollviewviewdelegate></whcrollviewviewdelegate></uiscrollviewdelegate></uikit>

2、封装Scrollview代码.m:

?
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
//  WHScrollAndPageView.m
//  循环滚动视图
//
//  Created by jereh on 15-3-15.
//  Copyright (c) 2015年 jereh. All rights reserved.
//
 
# import "WHScrollAndPageView.h"
 
@interface WHScrollAndPageView ()
{
     UIView *_firstView;
     UIView *_middleView;
     UIView *_lastView;
     
     float _viewWidth;
     float _viewHeight;
     
     NSTimer *_autoScrollTimer;
     
     UITapGestureRecognizer *_tap;
}
 
@end
 
@implementation WHScrollAndPageView
 
- (id)initWithFrame:(CGRect)frame
{
     self = [ super initWithFrame:frame];
     if (self) {
     
         _viewWidth = self.bounds.size.width;
         _viewHeight = self.bounds.size.height;
         
         //设置scrollview
         _scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake( 0 , 0 , _viewWidth, _viewHeight)];
         _scrollView.delegate = self;
         _scrollView.contentSize = CGSizeMake(_viewWidth * 3 , _viewHeight);
         _scrollView.showsHorizontalScrollIndicator = NO;
         _scrollView.pagingEnabled = YES;
         _scrollView.backgroundColor = [UIColor blackColor];
         _scrollView.delegate = self;
         [self addSubview:_scrollView];
         
         //设置分页
         _pageControl = [[UIPageControl alloc] initWithFrame:CGRectMake( 0 , _viewHeight- 30 , _viewWidth, 30 )];
         _pageControl.userInteractionEnabled = NO;
         _pageControl.currentPageIndicatorTintColor = [UIColor redColor];
         _pageControl.pageIndicatorTintColor = [UIColor whiteColor];
         [self addSubview:_pageControl];
         
         //设置单击手势
         _tap = [[UITapGestureRecognizer alloc]initWithTarget:self action: @selector (handleTap:)];
         _tap.numberOfTapsRequired = 1 ;
         _tap.numberOfTouchesRequired = 1 ;
         [_scrollView addGestureRecognizer:_tap];
     }
     return self;
}
 
#pragma mark 单击手势
-( void )handleTap:(UITapGestureRecognizer*)sender
{
     if ([_delegate respondsToSelector: @selector (didClickPage:atIndex:)]) {
         [_delegate didClickPage:self atIndex:_currentPage+ 1 ];
     }
}
 
#pragma mark 设置imageViewAry
-( void )setImageViewAry:(NSMutableArray *)imageViewAry
{
     if (imageViewAry) {
         _imageViewAry = imageViewAry;
         _currentPage = 0 ; //默认为第0页
         
         _pageControl.numberOfPages = _imageViewAry.count;
     }
     
     [self reloadData];
}
 
#pragma mark 刷新view页面
-( void )reloadData
{
     [_firstView removeFromSuperview];
     [_middleView removeFromSuperview];
     [_lastView removeFromSuperview];
     
     //从数组中取到对应的图片view加到已定义的三个view中
     if (_currentPage== 0 ) {
         _firstView = [_imageViewAry lastObject];
         _middleView = [_imageViewAry objectAtIndex:_currentPage];
         _lastView = [_imageViewAry objectAtIndex:_currentPage+ 1 ];
     }
     else if (_currentPage == _imageViewAry.count- 1 )
     {
         _firstView = [_imageViewAry objectAtIndex:_currentPage- 1 ];
         _middleView = [_imageViewAry objectAtIndex:_currentPage];
         _lastView = [_imageViewAry firstObject];
     }
     else
     {
         _firstView = [_imageViewAry objectAtIndex:_currentPage- 1 ];
         _middleView = [_imageViewAry objectAtIndex:_currentPage];
         _lastView = [_imageViewAry objectAtIndex:_currentPage+ 1 ];
     }
     
     //设置三个view的frame,加到scrollview上
     _firstView.frame = CGRectMake( 0 , 0 , _viewWidth, _viewHeight);
     _middleView.frame = CGRectMake(_viewWidth, 0 , _viewWidth, _viewHeight);
     _lastView.frame = CGRectMake(_viewWidth* 2 , 0 , _viewWidth, _viewHeight);
     [_scrollView addSubview:_firstView];
     [_scrollView addSubview:_middleView];
     [_scrollView addSubview:_lastView];
     
     //设置当前的分页
     _pageControl.currentPage = _currentPage;
     
     //显示中间页
     _scrollView.contentOffset = CGPointMake(_viewWidth, 0 );
}
 
#pragma mark scrollvie停止滑动
-( void )scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
     //手动滑动时候暂停自动替换
     [_autoScrollTimer invalidate];
     _autoScrollTimer = nil;
     _autoScrollTimer = [NSTimer scheduledTimerWithTimeInterval: 2 target:self selector: @selector (autoShowNextImage) userInfo:nil repeats:YES];
     
     //得到当前页数
     float x = _scrollView.contentOffset.x;
     
     //往前翻
     if (x<= 0 ) {
         if (_currentPage- 1 < 0 ) {
             _currentPage = _imageViewAry.count- 1 ;
         } else {
             _currentPage --;
         }
     }
     
     //往后翻
     if (x>=_viewWidth* 2 ) {
         if (_currentPage==_imageViewAry.count- 1 ) {
             _currentPage = 0 ;
         } else {
             _currentPage ++;
         }
     }
     
     [self reloadData];
}
 
#pragma mark 自动滚动
-( void )shouldAutoShow:(BOOL)shouldStart
{
     if (shouldStart)  //开启自动翻页
     {
         if (!_autoScrollTimer) {
             _autoScrollTimer = [NSTimer scheduledTimerWithTimeInterval: 2 target:self selector: @selector (autoShowNextImage) userInfo:nil repeats:YES];
         }
     }
     else   //关闭自动翻页
     {
         if (_autoScrollTimer.isValid) {
             [_autoScrollTimer invalidate];
             _autoScrollTimer = nil;
         }
     }
}
 
#pragma mark 展示下一页
-( void )autoShowNextImage
{
     if (_currentPage == _imageViewAry.count- 1 ) {
         _currentPage = 0 ;
     } else {
         _currentPage ++;
     }
     
     [self reloadData];
}
 
@end

3、使用封装好的Scrollview代码.m:

?
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
//  ViewController.m
//  循环滚动视图
//
//  Created by jereh on 15-3-15.
//  Copyright (c) 2015年 jereh. All rights reserved.
//
 
# import "ViewController.h"
# import "WHScrollAndPageView.h"
#define NUM 10
 
@interface ViewController ()<whcrollviewviewdelegate>
{
     WHScrollAndPageView *_whView;
}
 
@end
 
@implementation ViewController
 
- ( void )viewDidLoad
{
     [ super viewDidLoad];
     
     //创建view (view中包含UIScrollView、UIPageControl,设置frame)
     _whView = [[WHScrollAndPageView alloc] initWithFrame:CGRectMake( 0 , 44 , 320 , 400 )];
     
     //把N张图片放到imageview上
     NSMutableArray *tempAry = [NSMutableArray array];
     for ( int i= 1 ; i<num; _whview= "" _whview.delegate= "self;" animated= "" imageview= "[[UIImageView" imageview.image= "[UIImage" index= "" mark= "" nsstring= "" pragma= "" pre= "" self.view= "" tempary= "" uiimageview= "" view= "" whscrollandpageview= "" ><p> </p></num;></whcrollviewviewdelegate>