首页 > 代码库 > [iOS基础控件 - 5.4] 广告分页代码(UIScrollView制作)

[iOS基础控件 - 5.4] 广告分页代码(UIScrollView制作)

A.概念
例子就是桌面的APP列表,当APP数量超过一个屏幕,自动进行分页
 
B.实现思路
1.创建一个UIScrollView,这里设置为宽度跟屏幕相同,高度1/4屏幕高度左右
2.使用代码在UIScrollView中添加ImageView,横向放入多张ImageView
3.设置UIScrollView的contentSize为所有图片的宽度总和
4.要保证UIScrollView的宽度等于一张ImageView的宽度,才能正确分页
 
C.相关属性
设置属性pageEnable = YES,UIScrollView会被分割成多个独立页面,进行分页显示
一般使用UIPageControl增强效果,UIPageControl常见属性:
 1     // 总页数 2     @property(nonatomic) NSInteger numberOfPages;          // default is 0 3     // 当前页码 4     @property(nonatomic) NSInteger currentPage; 5     // 只有一页的时候隐藏页码 6     @property(nonatomic) BOOL hidesForSinglePage;          // hide the the indicator if there is only one page. default is NO 7     // 其他页码指示颜色 8     @property(nonatomic,retain) UIColor *pageIndicatorTintColor; 9     // 当前页码指示颜色10     @property(nonatomic,retain) UIColor *currentPageIndicatorTintColor;
 
 
D.实现步骤
1. 创建一个UIScrollView,设置位置、尺寸
Image(61)
 
2.用代码加载多张图片
 1     CGFloat imageWidth = 300; 2     CGFloat imageHeight = 130; 3     CGFloat imageY = 0; 4     5     for (int i=0; i<5; i++) { 6         CGFloat imageX = i * imageWidth; 7         UIImageView *currentImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:[NSString stringWithFormat:@"img_%02d", i+1]]]; 8         currentImageView.frame = CGRectMake(imageX, imageY, imageWidth, imageHeight); 9        10         [self.scrollView addSubview:currentImageView];11     }
 
3.设置contentSize
1     // 设置可以拖曳的范围,只允许横向拖曳,而且范围是所有的图片宽度总和2     self.scrollView.contentSize = CGSizeMake(5 * imageWidth, 0);
 
4.开启 pageEnable = YES
     每次拖曳至少滑动1个UIScrollView宽度单位,设置UIScrollView的宽度为图片的宽度之后,刚好翻过一页。
1     // 开启翻页模式,每次拖曳都会滑动一个UIScrollView宽度单位2     self.scrollView.pagingEnabled = YES;
 
没有开启之前,切换两幅图片的时候终止拖曳,会停留在那一刻的显示状态
Image(62)
 
开启之后效果就像书本翻页一样
Image(63)
 
 
5.加入pageControl
pageControl要放在UIScrollView外,而且要比UIScrollView更前,才能正常显示
Image(64)
 
 
6.使用代码设置pageControl
pageControl属性:
 1     // 总页数 2     @property(nonatomic) NSInteger numberOfPages;          // default is 0 3     // 当前页码 4     @property(nonatomic) NSInteger currentPage; 5     // 只有一页的时候隐藏页码 6     @property(nonatomic) BOOL hidesForSinglePage;          // hide the the indicator if there is only one page. default is NO 7     // 其他页码指示颜色 8     @property(nonatomic,retain) UIColor *pageIndicatorTintColor; 9     // 当前页码指示颜色10     @property(nonatomic,retain) UIColor *currentPageIndicatorTintColor;
 
(1)要手动设置pageControl,它才能正常工作
1     // 设置pageControl2     self.pageControl.numberOfPages = 5;3     self.pageControl.pageIndicatorTintColor = [UIColor blackColor];4    5     //设置delegate6     self.scrollView.delegate = self;
 
(2)控制器遵守UIScrollViewDelegate协议,在 scrollViewDidScroll中动态设置当前页码
1 /** 当scrollView滚动的时候调用 */2 - (void)scrollViewDidScroll:(UIScrollView *)scrollView {3     CGFloat scrollWidth = scrollView.frame.size.width;4    5     // 当一副图片拖曳超过一半的时候就重新计算页码6     int page = (scrollView.contentOffset.x + scrollWidth * 0.5) / scrollWidth;7    8     self.pageControl.currentPage = page;9 }
 
Image(65)
 
 
7.使用定时器NSTimer自动换页
(1)添加定时器
1     // 创建定时器2     NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(nextImage) userInfo:nil repeats:YES];
 
(2)创建定时器调用的方法
 1 - (void) nextImage { 2     // 1.增加pageControl的页码,这里不能直接操作currentPage,因为这样会和scrollViewDidScroll的页码计算冲突,应该是滚动画面,触发scrollViewDidScroll进行页码转换 3     int pageNo = 0; 4     if (self.pageControl.currentPage == (IMAGE_COUNT - 1)) { 5         pageNo = 0; 6     } 7     else { 8         pageNo = self.pageControl.currentPage + 1; 9     }10  11     // 2.计算scrollView的滑动位置12     CGFloat offsetX = pageNo * self.scrollView.frame.size.width;13     CGPoint offset = CGPointMake(offsetX, 0);14    15     // 移动一页,带动画效果16     [self.scrollView setContentOffset:offset  animated:YES];17 }
 
(3)定时器的弱点,在单线程运行时,得不到线程资源的时候,定时器定制运行,事件累积,得到资源之后才一起运行,这里有两种情况:
 
a.手动拖曳阻止了定时器
     解决:销毁定时器,确保资源之后再创建一个
 1 // 开始手动拖曳的时候,销毁定时器 2 - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { 3     [self.timer invalidate]; // 调用了invalidate之后再不可用了 4     self.timer = nil; 5 } 6  7 // 结束手动拖曳,重新定义定时器 8 - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate { 9     [self addTimer];10 }11 12 // 添加定时器13 - (void) addTimer {14     self.timer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(nextImage) userInfo:nil repeats:YES];15 }
 
b.外部可刷新的控件抢占了所有线程资源
如下图中,添加了一个TextView,当拖曳其滚动条时,占用了所有线程刷新资源,定时器就被阻断了
Image(66)
 
解决:争取主线程资源来刷新(分享资源)
1 // 添加定时器2 - (void) addTimer {3     self.timer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(nextImage) userInfo:nil repeats:YES];4    5     // 获得主线程资源,防止另外的如可滚动控件的资源全占用6     [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];7 }
 
 
E.滚动页的优化
1.只使用3个ImageView加载图片,动态加载图片
2.无限滚动
 
 
F.主要代码:
  1 //  2 //  ViewController.m  3 //  ScrollViewPage  4 //  5 //  Created by hellovoidworld on 14/11/28.  6 //  Copyright (c) 2014年 hellovoidworld. All rights reserved.  7 //  8   9 #import "ViewController.h" 10  11 #define IMAGE_COUNT 5 12  13 @interface ViewController () <UIScrollViewDelegate> 14 @property (weak, nonatomic) IBOutlet UIScrollView *scrollView; // 滚动控件 15 @property (weak, nonatomic) IBOutlet UIPageControl *pageControl; // 页码控件 16  17 @property(nonatomic, strong) NSTimer *timer; // 定时器 18  19 @end 20  21 @implementation ViewController 22  23 - (void)viewDidLoad { 24     [super viewDidLoad]; 25     // Do any additional setup after loading the view, typically from a nib. 26     27  28     29     CGFloat imageWidth = 300; 30     CGFloat imageHeight = 130; 31     CGFloat imageY = 0; 32     33     for (int i=0; i<IMAGE_COUNT; i++) { 34         CGFloat imageX = i * imageWidth; 35         UIImageView *currentImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:[NSString stringWithFormat:@"img_%02d", i+1]]]; 36         currentImageView.frame = CGRectMake(imageX, imageY, imageWidth, imageHeight); 37         38         [self.scrollView addSubview:currentImageView]; 39     } 40     41     // 设置可以拖曳的范围,只允许横向拖曳,而且范围是所有的图片宽度总和 42     self.scrollView.contentSize = CGSizeMake(IMAGE_COUNT * imageWidth, 0); 43     44     // 开启翻页模式,每次拖曳都会滑动一个UIScrollView宽度单位 45     self.scrollView.pagingEnabled = YES; 46     47     // 设置pageControl 48     self.pageControl.numberOfPages = 5; 49     self.pageControl.pageIndicatorTintColor = [UIColor blackColor]; 50     self.pageControl.currentPageIndicatorTintColor = [UIColor redColor]; 51     52     // 设置delegate 53     self.scrollView.delegate = self; 54     55     // 创建定时器 56     [self addTimer]; 57 } 58  59 - (void)didReceiveMemoryWarning { 60     [super didReceiveMemoryWarning]; 61     // Dispose of any resources that can be recreated. 62 } 63  64  65 /** 当scrollView滚动的时候调用 */ 66 - (void)scrollViewDidScroll:(UIScrollView *)scrollView { 67     CGFloat scrollWidth = scrollView.frame.size.width; 68     69     // 当一副图片拖曳超过一半的时候就重新计算页码 70     int page = (scrollView.contentOffset.x + scrollWidth * 0.5) / scrollWidth; 71     72     self.pageControl.currentPage = page; 73 } 74  75 - (void) nextImage { 76     // 1.增加pageControl的页码,这里不能直接操作currentPage,因为这样会和scrollViewDidScroll的页码计算冲突,应该是滚动画面,触发scrollViewDidScroll进行页码转换 77     int pageNo = 0; 78     if (self.pageControl.currentPage == (IMAGE_COUNT - 1)) { 79         pageNo = 0; 80     } 81     else { 82         pageNo = self.pageControl.currentPage + 1; 83     } 84  85     // 2.计算scrollView的滑动位置 86     CGFloat offsetX = pageNo * self.scrollView.frame.size.width; 87     CGPoint offset = CGPointMake(offsetX, 0); 88     89     // 移动一页,带动画效果 90     [self.scrollView setContentOffset:offset  animated:YES]; 91 } 92  93 // 开始手动拖曳的时候,销毁定时器 94 - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { 95     [self.timer invalidate]; // 调用了invalidate之后再不可用了 96     self.timer = nil; 97 } 98  99 // 结束手动拖曳,重新定义定时器100 - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {101     [self addTimer];102 }103 104 // 添加定时器105 - (void) addTimer {106     self.timer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(nextImage) userInfo:nil repeats:YES];107    108     // 获得主线程资源,防止另外的如可滚动控件的资源全占用109     [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];110 }111 112 @end

 

 

[iOS基础控件 - 5.4] 广告分页代码(UIScrollView制作)