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

时间:2024-01-06 20:41:50
A.概念
例子就是桌面的APP列表,当APP数量超过一个屏幕,自动进行分页
B.实现思路
1.创建一个UIScrollView,这里设置为宽度跟屏幕相同,高度1/4屏幕高度左右
2.使用代码在UIScrollView中添加ImageView,横向放入多张ImageView
3.设置UIScrollView的contentSize为所有图片的宽度总和
4.要保证UIScrollView的宽度等于一张ImageView的宽度,才能正确分页
C.相关属性
设置属性pageEnable = YES,UIScrollView会被分割成多个独立页面,进行分页显示
一般使用UIPageControl增强效果,UIPageControl常见属性:
     // 总页数
@property(nonatomic) NSInteger numberOfPages; // default is 0
// 当前页码
@property(nonatomic) NSInteger currentPage;
// 只有一页的时候隐藏页码
@property(nonatomic) BOOL hidesForSinglePage; // hide the the indicator if there is only one page. default is NO
// 其他页码指示颜色
@property(nonatomic,retain) UIColor *pageIndicatorTintColor;
// 当前页码指示颜色
@property(nonatomic,retain) UIColor *currentPageIndicatorTintColor;
D.实现步骤
1. 创建一个UIScrollView,设置位置、尺寸
[iOS基础控件 - 5.4] 广告分页代码(UIScrollView制作)
2.用代码加载多张图片
     CGFloat imageWidth = ;
CGFloat imageHeight = ;
CGFloat imageY = ; for (int i=; i<; i++) {
CGFloat imageX = i * imageWidth;
UIImageView *currentImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:[NSString stringWithFormat:@"img_%02d", i+]]];
currentImageView.frame = CGRectMake(imageX, imageY, imageWidth, imageHeight); [self.scrollView addSubview:currentImageView];
}
3.设置contentSize
     // 设置可以拖曳的范围,只允许横向拖曳,而且范围是所有的图片宽度总和
self.scrollView.contentSize = CGSizeMake( * imageWidth, );
4.开启 pageEnable = YES
     每次拖曳至少滑动1个UIScrollView宽度单位,设置UIScrollView的宽度为图片的宽度之后,刚好翻过一页。
     // 开启翻页模式,每次拖曳都会滑动一个UIScrollView宽度单位
self.scrollView.pagingEnabled = YES;
没有开启之前,切换两幅图片的时候终止拖曳,会停留在那一刻的显示状态
[iOS基础控件 - 5.4] 广告分页代码(UIScrollView制作)
开启之后效果就像书本翻页一样
[iOS基础控件 - 5.4] 广告分页代码(UIScrollView制作)
5.加入pageControl
pageControl要放在UIScrollView外,而且要比UIScrollView更前,才能正常显示
[iOS基础控件 - 5.4] 广告分页代码(UIScrollView制作)
6.使用代码设置pageControl
pageControl属性:
     // 总页数
@property(nonatomic) NSInteger numberOfPages; // default is 0
// 当前页码
@property(nonatomic) NSInteger currentPage;
// 只有一页的时候隐藏页码
@property(nonatomic) BOOL hidesForSinglePage; // hide the the indicator if there is only one page. default is NO
// 其他页码指示颜色
@property(nonatomic,retain) UIColor *pageIndicatorTintColor;
// 当前页码指示颜色
@property(nonatomic,retain) UIColor *currentPageIndicatorTintColor;
(1)要手动设置pageControl,它才能正常工作
     // 设置pageControl
self.pageControl.numberOfPages = ;
self.pageControl.pageIndicatorTintColor = [UIColor blackColor]; //设置delegate
self.scrollView.delegate = self;
(2)控制器遵守UIScrollViewDelegate协议,在 scrollViewDidScroll中动态设置当前页码
 /** 当scrollView滚动的时候调用 */
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
CGFloat scrollWidth = scrollView.frame.size.width; // 当一副图片拖曳超过一半的时候就重新计算页码
int page = (scrollView.contentOffset.x + scrollWidth * 0.5) / scrollWidth; self.pageControl.currentPage = page;
}
[iOS基础控件 - 5.4] 广告分页代码(UIScrollView制作)
7.使用定时器NSTimer自动换页
(1)添加定时器
     // 创建定时器
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval: target:self selector:@selector(nextImage) userInfo:nil repeats:YES];
(2)创建定时器调用的方法
 - (void) nextImage {
// 1.增加pageControl的页码,这里不能直接操作currentPage,因为这样会和scrollViewDidScroll的页码计算冲突,应该是滚动画面,触发scrollViewDidScroll进行页码转换
int pageNo = ;
if (self.pageControl.currentPage == (IMAGE_COUNT - )) {
pageNo = ;
}
else {
pageNo = self.pageControl.currentPage + ;
} // 2.计算scrollView的滑动位置
CGFloat offsetX = pageNo * self.scrollView.frame.size.width;
CGPoint offset = CGPointMake(offsetX, ); // 移动一页,带动画效果
[self.scrollView setContentOffset:offset animated:YES];
}
(3)定时器的弱点,在单线程运行时,得不到线程资源的时候,定时器定制运行,事件累积,得到资源之后才一起运行,这里有两种情况:
a.手动拖曳阻止了定时器
     解决:销毁定时器,确保资源之后再创建一个
 // 开始手动拖曳的时候,销毁定时器
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
[self.timer invalidate]; // 调用了invalidate之后再不可用了
self.timer = nil;
} // 结束手动拖曳,重新定义定时器
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
[self addTimer];
} // 添加定时器
- (void) addTimer {
self.timer = [NSTimer scheduledTimerWithTimeInterval: target:self selector:@selector(nextImage) userInfo:nil repeats:YES];
}
b.外部可刷新的控件抢占了所有线程资源
如下图中,添加了一个TextView,当拖曳其滚动条时,占用了所有线程刷新资源,定时器就被阻断了
[iOS基础控件 - 5.4] 广告分页代码(UIScrollView制作)
解决:争取主线程资源来刷新(分享资源)
 // 添加定时器
- (void) addTimer {
self.timer = [NSTimer scheduledTimerWithTimeInterval: target:self selector:@selector(nextImage) userInfo:nil repeats:YES]; // 获得主线程资源,防止另外的如可滚动控件的资源全占用
[[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
}
E.滚动页的优化
1.只使用3个ImageView加载图片,动态加载图片
2.无限滚动
F.主要代码:
 //
// ViewController.m
// ScrollViewPage
//
// Created by hellovoidworld on 14/11/28.
// Copyright (c) 2014年 hellovoidworld. All rights reserved.
// #import "ViewController.h" #define IMAGE_COUNT 5 @interface ViewController () <UIScrollViewDelegate>
@property (weak, nonatomic) IBOutlet UIScrollView *scrollView; // 滚动控件
@property (weak, nonatomic) IBOutlet UIPageControl *pageControl; // 页码控件 @property(nonatomic, strong) NSTimer *timer; // 定时器 @end @implementation ViewController - (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib. CGFloat imageWidth = ;
CGFloat imageHeight = ;
CGFloat imageY = ; for (int i=; i<IMAGE_COUNT; i++) {
CGFloat imageX = i * imageWidth;
UIImageView *currentImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:[NSString stringWithFormat:@"img_%02d", i+]]];
currentImageView.frame = CGRectMake(imageX, imageY, imageWidth, imageHeight); [self.scrollView addSubview:currentImageView];
} // 设置可以拖曳的范围,只允许横向拖曳,而且范围是所有的图片宽度总和
self.scrollView.contentSize = CGSizeMake(IMAGE_COUNT * imageWidth, ); // 开启翻页模式,每次拖曳都会滑动一个UIScrollView宽度单位
self.scrollView.pagingEnabled = YES; // 设置pageControl
self.pageControl.numberOfPages = ;
self.pageControl.pageIndicatorTintColor = [UIColor blackColor];
self.pageControl.currentPageIndicatorTintColor = [UIColor redColor]; // 设置delegate
self.scrollView.delegate = self; // 创建定时器
[self addTimer];
} - (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
} /** 当scrollView滚动的时候调用 */
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
CGFloat scrollWidth = scrollView.frame.size.width; // 当一副图片拖曳超过一半的时候就重新计算页码
int page = (scrollView.contentOffset.x + scrollWidth * 0.5) / scrollWidth; self.pageControl.currentPage = page;
} - (void) nextImage {
// 1.增加pageControl的页码,这里不能直接操作currentPage,因为这样会和scrollViewDidScroll的页码计算冲突,应该是滚动画面,触发scrollViewDidScroll进行页码转换
int pageNo = ;
if (self.pageControl.currentPage == (IMAGE_COUNT - )) {
pageNo = ;
}
else {
pageNo = self.pageControl.currentPage + ;
} // 2.计算scrollView的滑动位置
CGFloat offsetX = pageNo * self.scrollView.frame.size.width;
CGPoint offset = CGPointMake(offsetX, ); // 移动一页,带动画效果
[self.scrollView setContentOffset:offset animated:YES];
} // 开始手动拖曳的时候,销毁定时器
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
[self.timer invalidate]; // 调用了invalidate之后再不可用了
self.timer = nil;
} // 结束手动拖曳,重新定义定时器
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
[self addTimer];
} // 添加定时器
- (void) addTimer {
self.timer = [NSTimer scheduledTimerWithTimeInterval: target:self selector:@selector(nextImage) userInfo:nil repeats:YES]; // 获得主线程资源,防止另外的如可滚动控件的资源全占用
[[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
} @end