功能:
在我们刚刚打开App时,一般首页会有一个广告展示的页面,能显示几张自动翻滚的图片,还能通过点击来跳转到对应页。
如下图:
实现
这是一个给项目中Controller类用的CustomView,需要在多个Controller中使用,可以单独写一个类,继承UIView,然后定义delegate和datasource,在Controller类里实现delegate和datasouce方法,来显示的具体内容。这个CustomView主要通过一个ScrollView+PageView实现。Scrolview上Add了三个SubViews:当前显示的View、显示View的前一个View、显示View的后一个View。
具体实现
1、创建控件并显示
自定义了一个CustomView,有两种方法来init:代码和xib文件。这时会调用CustomView的不同init方法。从代码创建时,调用initWithFrame;而从xib文件创建时,调用initWithCoder。
这边用代码来创建控件。首先会调用initwithframe方法来创建控件并设置控件frame。在这个方法里,创建了scrollview和pageview,并add到当前类的view中。_scrollview的contentoffset为frame的width,因为控件显示的是scrollview的中间页。
//创建控件,写在Controller类的loadview方法中
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
_scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
_scrollView.delegate = self;
_scrollView.contentSize = CGSizeMake(self.frame.size.width * 3, self.frame.size.height);
_scrollView.showsHorizontalScrollIndicator = NO;
_scrollView.contentOffset = CGPointMake(self.frame.size.width, 0);
_scrollView.pagingEnabled = YES;
[self addSubview:_scrollView];
CGRect rect = CGRectMake(80, self.bounds.size.height - 20, 160, 20);
_pageControl = [[UIPageControl alloc] initWithFrame:rect];
_pageControl.userInteractionEnabled = NO;
[self addSubview:_pageControl];
//控件显示的页面
_curPage = 0;
}
return self;
}
控件创建了,不过内容是空的。怎么添加具体内容呢?当然是在Controller类中实现delegate和datasource方法了。
在CustomView的.h文件中:
//内存管理方式是MRC
@property (nonatomic,assign,setter = setDataource:) id<XLCycleScrollViewDatasource> datasource;
@protocol XLCycleScrollViewDatasource <NSObject>
@required
- (NSInteger)numberOfPages;
- (UIView *)pageAtIndex:(NSInteger)index;
@end
在Controller类中,CustomView.dataSouce = self;
程序就跑到CustomView的setDataource;
方法中。在这个方法里,我们就可以设置显示的内容。
- (void)setDataource:(id<XLCycleScrollViewDatasource>)datasource
{
_datasource = datasource;
[self reloadData];
}
- (void)reloadData
{
_totalPages = [_datasource numberOfPages];
if (_totalPages == 0) {
return;
}
_pageControl.numberOfPages = _totalPages;
[self loadData];
}
- (void)loadData
{
_pageControl.currentPage = _curPage;
//从scrollView上移除所有的subview
NSArray *subViews = [_scrollView subviews];
if([subViews count] != 0) {
[subViews makeObjectsPerformSelector:@selector(removeFromSuperview)];
}
//通过_curPage(当前显示的页面),来设置显示在Scrollview上的3个View(保存在_curViews中)
[self getDisplayImagesWithCurpage:_curPage];
for (int i = 0; i < 3; i++) {
UIView *v = [_curViews objectAtIndex:i];
v.userInteractionEnabled = YES;
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self
action:@selector(handleTap:)];
[v addGestureRecognizer:singleTap];
[singleTap release];
v.frame = CGRectOffset(v.frame, v.frame.size.width * i, 0);
[_scrollView addSubview:v];
}
//中间页为显示页
[_scrollView setContentOffset:CGPointMake(_scrollView.frame.size.width, 0)];
}
在设置_datasource = datasource;
后,就可以通过[_datasouce functionName];
来调用Controller类中实现的datasouce方法了。_curViews是一个NSMutableArray
类,通过_curPage具体设置其中的3个object。
/**
* 获取需要显示的3个View
*
* @param page 当前显示页
*/
- (void)getDisplayImagesWithCurpage:(int)page {
int pre = [self validPageValue:_curPage-1];
int last = [self validPageValue:_curPage+1];
if (!_curViews) {
_curViews = [[NSMutableArray alloc] init];
}
[_curViews removeAllObjects];
[_curViews addObject:[_datasource pageAtIndex:pre]];
[_curViews addObject:[_datasource pageAtIndex:page]];
[_curViews addObject:[_datasource pageAtIndex:last]];
}
可以看到,在loadData
方法中,为每个View添加了Tap手势,实现点击功能。
到这里,控件创建了并在Controller上显示了第一页。理一理,假设Controller类为A,CustomView为B。[A loadView]
-> [B initWithFrame]
-> A类中B.dataSource = self;
->[B setDataSouce:]
2、滑动控件,View切换
通过- (void)scrollViewDidScroll:
要捕获ScrolView的滚动事件,可以获取当前ScrollView的contentOffSSet。
#pragma mark - UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)aScrollView {
int x = aScrollView.contentOffset.x;
//往下翻一张
if(x == (2*self.frame.size.width)) {
_curPage = [self validPageValue:_curPage+1];
[self loadData];
}
//往上翻
if(x == 0) {
_curPage = [self validPageValue:_curPage-1];
[self loadData];
}
}
因为设置了ScrollVeiw的pageEnabled属性未yes,ScrollView就会根据view来设置ContentOffSet,界面不会停留在某个view的中间。通过[self loadData]
来重新设置ScrollView显示的内容。
结束了
到这儿,功能就实现了,还可以通过添加NSTimer来动态显示,就是可以每隔N秒,自动切换图片。
点击下载代码
我觉得有意思的一点:界面都是在代码运行完后显示的,就是说,一个关于界面的方法,在return
后,界面才会更新(可以通过GCD来设置界面更新的顺序)。在- (void)scrollViewDidScroll:
方法中,假如界面滑动到了下一个View,这个View替换了显示的View时,就调用了[self loadData]
方法,这个方法里,又重新设置了ScrollView的内容,又刷新了ScrollView。就显示下一个内容来说,看着是很顺畅显示到了下个页面,中间的调用[self loadDta]
页面的刷新,完全被覆盖了。神奇~
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。