擺脫第三方庫系列(二)- 自己寫一個滾動廣告
前言
擺脫第三方庫系列第二章,我將介紹滾動廣告的寫法。在一些信息聚合類APP中滾動廣告非常常見或者說必不可少,他可以不需要用戶操作展示一些開發者想展示的東西,原理其實也很簡單。我寫的滾動廣告主要實現自動滾動和循環滾動這兩個功能,至于廣告的點擊事件或者美化這都是后話了。
滾動廣告基本原理
其實只要是滾動的東西都離不開UISCrollView,滾動廣告的原理就是在一個橫向的UISCrollView上放置多張圖片并插入文字,然后設置時間自動翻頁,點擊事件可以通過設置代理方法完成。
而循環播放的原理是這樣的,假使我們有五張廣告圖需要播放,那么我們在UISCrollView應該插入七張圖片,除開頭尾兩張后中間剩下的五張按順序放置我們要展示的廣告,那么頭尾兩部分放什么呢?
頭部分應該放最后一張也就是第五張廣告圖,尾部分應該放第一張廣告圖
這樣當用戶看到第一張廣告圖并向左移動時就會出現第五張廣告圖,然后我們應該在代碼中使用一些“小手段”,當廣告頁滾動到頭頁的時候應該自動跳到倒數第二頁也就是第五張廣告頁。這樣就完成了一個看起來可以循環的輪播廣告了。
代碼實現
先上完成效果圖
接下來上代碼,先創建一個繼承于UIView的子類RollView,這里不推薦直接繼承于UISCrollView,那樣可能會因為控件層次問題出現有些控件被覆蓋了。
接口部分
RollView接口部分如下
@interface RollView : UIView<UIScrollViewDelegate>
@property (nonatomic, strong) UIScrollView *rollScrollView;
@property (nonatomic, strong) NSMutableArray *imageArray;
@property (nonatomic, strong) UIImageView *rollImgView;
@property (nonatomic, strong) UIPageControl *pageControl;
@property (nonatomic, strong) NSTimer *timer;
@end
UIPageControl是一個蘋果公司給的頁面小點的控件,也是滾動廣告比較常見的需要添加的控件。而imageArray
主要是為了存儲多個廣告圖,可以自己封裝一個UIImageView這樣就可以讓自己的廣告更加個性了。
為了簡化代碼先宏定義下
#define COUNT self.imageArray.count
define SVIEWWIDTH self.frame.size.width
define SVIEWHEIGHT self.frame.size.height
</code></pre>
RollView初始化
先看自身的初始化方法,很簡單,addNSTimer
方法是添加一個定時器滾動,一會再介紹。
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if(self){
[self addSubview:self.rollScrollView];
[self addSubview:self.pageControl];
[self addNSTimer];
}
return self;
}
各個控件get方法
接下來看get方法
- (UIScrollView *)rollScrollView
{
if (_rollScrollView == nil) {
_rollScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, SVIEWWIDTH, SVIEWHEIGHT)];
_rollScrollView.delegate = self;
_rollScrollView.contentSize = CGSizeMake((COUNT + 2) * SVIEWWIDTH, SVIEWHEIGHT);
//使子視圖imageview自動適配scrollview的大小
[_rollScrollView setAutoresizesSubviews:YES];
//將scrollview設成分頁形式
[_rollScrollView setPagingEnabled:YES];
//隱藏scrollview兩邊的滾動條
[_rollScrollView setShowsVerticalScrollIndicator:NO];
[_rollScrollView setShowsHorizontalScrollIndicator:NO];
//設置scrollview初始的位置為第二部分來顯示第一張廣告
_rollScrollView.contentOffset = CGPointMake(SVIEWWIDTH, 0);
}
return _rollScrollView;
}
什么是UISCrollView的contentSize我在這篇文章講過。由于要循環播放所以要加兩張圖片,所以寬度為(COUNT + 2) * SVIEWWIDTH
,其他解釋寫在注釋里了。
然后是pageControl的get方法。
- (UIPageControl *)pageControl
{
if (_pageControl == nil) {
_pageControl = [[UIPageControl alloc] initWithFrame:CGRectMake((SVIEWWIDTH - _pageControl.bounds.size.width)/2, SVIEWHEIGHT - 10, _pageControl.bounds.size.width, _pageControl.bounds.size.height)];
_pageControl.currentPageIndicatorTintColor = [UIColor whiteColor];
_pageControl.pageIndicatorTintColor = [UIColor grayColor];
[_pageControl setNumberOfPages:COUNT];
}
return _pageControl;
}
其中currentPageIndicatorTintColor
是點移動到當前點時的顏色,pageIndicatorTintColor
是沒移動到的點的顏色。
然后在imageArray
中添加我們的廣告圖片,由于NSArray是可以存儲任何對象類型的,所以我們可以存儲廣告圖也可以直接存UIImageView,這里我是存了任意的五張UIImage,就不上代碼了,直接看rollImgView
。
- (UIImageView )rollImgView
{
if (_rollImgView == nil) {
//第一個放最后一個圖片
_rollImgView = [[UIImageView alloc] init];
_rollImgView.frame = CGRectMake(0, 0, SVIEWWIDTH, SVIEWHEIGHT);
[_rollImgView setImage:[_imageArray objectAtIndex:(COUNT - 1)]];
[self.rollScrollView addSubview:_rollImgView];
//最后一個放第一張圖片
_rollImgView = [[UIImageView alloc] init];
_rollImgView.frame = CGRectMake(SVIEWWIDTH (COUNT + 1), 0, SVIEWWIDTH, SVIEWHEIGHT);
[_rollImgView setImage:[_imageArray objectAtIndex:0]];
[self.rollScrollView addSubview:_rollImgView];
for (int i = 0; i < COUNT; i++) {
_rollImgView = [[UIImageView alloc] init];
_rollImgView.frame = CGRectMake(SVIEWWIDTH * (i + 1), 0, SVIEWWIDTH, SVIEWHEIGHT);
[_rollImgView setImage:[_imageArray objectAtIndex:i]];
[self.rollScrollView addSubview:_rollImgView];
}
}
return _rollImgView;
}
</code></pre>
這里需要注意的就是每個圖片需要放置的frame,想不明白的自己動手畫個草稿就一目了然了。我是設置了五張廣告圖片所以我們應該用七張UIImageView,所以要初始化七次添加七次,可能有點不合理,有更好的辦法希望留言告訴我。
scrollView代理部分
- (void)scrollViewDidScroll:(UIScrollView )scrollView
{
if (scrollView.contentOffset.x == 0) {
self.rollScrollView.contentOffset = CGPointMake(COUNT SVIEWWIDTH, 0);
self.pageControl.currentPage = (COUNT - 1);
}else if (scrollView.contentOffset.x == (COUNT + 1) * SVIEWWIDTH){
self.rollScrollView.contentOffset = CGPointMake(SVIEWWIDTH, 0);
self.pageControl.currentPage = 0;
}else{
int pagenum = (round(scrollView.contentOffset.x/self.rollImgView.frame.size.width) - 1);
[self.pageControl setCurrentPage:pagenum];
}
}
(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
[self removeNSTimer];
}
(void)scrollViewDidEndDragging:(UIScrollView )scrollView willDecelerate:(BOOL)decelerate
{
[self addNSTimer];
}
</code></pre>
主要代碼都在scrollViewDidScroll
方法中,就是在scrollview滾動時調用的方法。這里主要就是前面提到的實現循環滾動的“小手段”了。
當scrollView.contentOffset.x == 0
時,說明的此時顯示的是頭imageview即第五張廣告,那么我們需要跳動到第五張廣告也就是第六張imageview來完成循環效果,同時也別忘記改版pageControl的當前點。由于是5個點,那么下標是0-4,所以是標到(COUNT - 1)
處。
scrollView.contentOffset.x == (COUNT + 1)
SVIEWWIDTH</code>表示的是在尾imageview時的操作。</p>
如果既不在頭也不在尾,我們只需要在滾動時改變標簽點就可以了。其中round
是表示取四舍五入的整數,這樣改變標簽點更合理。
下面兩個方法是說我們鼠標按住scrollview時我們應該取消計時器不再計時,松開手時再開始計時。
計時器
- (void)addNSTimer
{
if (self.timer == nil) {
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:4 target:self selector:@selector(nextPage) userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop]addTimer:timer forMode:NSRunLoopCommonModes];
self.timer = timer;
}
}
(void)removeNSTimer
{
[self.timer invalidate];
self.timer =nil;
}
(void)nextPage
{
if (self.rollScrollView.contentOffset.x == ((COUNT) * self.rollImgView.frame.size.width)) {
[self.rollScrollView scrollRectToVisible:CGRectMake(SVIEWWIDTH, 0, SVIEWWIDTH, SVIEWHEIGHT) animated:YES];
}else{
[self.rollScrollView scrollRectToVisible:CGRectMake(self.rollScrollView.contentOffset.x + self.rollImgView.frame.size.width, 0, SVIEWWIDTH, SVIEWHEIGHT) animated:YES];
}
}
</code></pre>
這里主要是三個自定義方法,顧名思義都比較簡單,這里不做詳細介紹了。
接下來就將RollView添加到ViewController中就可以展示了。
總結
這樣滾動廣告差不多就介紹完了,我只是介紹了基本原理,在我們的開發中肯定是不能完全滿足需求的,所以還要加一些自定義的更改。比如用自定義的imageview并用代理方法增加點擊事件,或者直接不用imageview用buttun。demo我也會放到我的github上。
還是那句話,如果有錯還請指出,萬分感謝。
相關文章
來源:http://cbsfly.github.io/ios/rollview