上篇文章讲到指示器的添加,今天我们来添加一个scrollview,使得指示器能跟随scrollview变化,scrollview也能根据指示器的位置不同更改自己需要显示的view。
还是以网易音乐的界面为例,红色指示器下面对应了一个view,其它三个指示器按钮也对应了各自的view
所以,我们需要创建一个scrollview作为底层view,然后在scrollview上添加4个ViewController来对应指示器4个按钮的页面。
创建好4个ViewController文件后,我们要实例化他们,并添加到当前view的子控制器中。
- (void)addChildViews
{
CommendViewController *cmmVC = [[CommendViewController alloc] init];
cmmVC.title = @"个性推荐";
[self addChildViewController:cmmVC];
ListViewController *listVC = [[ListViewController alloc] init];
listVC.title = @"歌单";
[self addChildViewController:listVC];
RadioViewController *radioVC = [[RadioViewController alloc] init];
radioVC.title = @"主播频道";
[self addChildViewController:radioVC];
LeaderBoardViewController *leaderVC = [[LeaderBoardViewController alloc] init];
leaderVC.title = @"排行榜";
[self addChildViewController:leaderVC];
}
记得在viewDidLoad函数中调用它!!
接下来我们添加scrollview吧
/**
* 创建Scrollview咯~
*
* @return void
*/
- (void)initScrollView
{
//禁止系统自动调整ScrollView的布局,以免影响我们自己的布局
self.automaticallyAdjustsScrollViewInsets = NO;
//创建scrollview
UIScrollView *scrollView = [[UIScrollView alloc] init];
scrollView.frame = [UIScreen mainScreen].bounds;
//使用scrollview的分页功能,如果拖动没到页面的一半,不会切换到下一页
scrollView.pagingEnabled = YES;
//设置scrollview的内容显示大小,一共有4个屏幕宽度
scrollView.contentSize = CGSizeMake(self.view.width * 4, 0);
scrollView.backgroundColor = [UIColor lightGrayColor];
//设置scrollview的代理
scrollView.delegate = self;
//把scrollview添加到view的最底层
[self.view insertSubview:scrollView atIndex:0];
//保存scrollview到属性,方便后面调用
self.contentScrollView = scrollView;
}
同样,记得在ViewDidLoad函数中调用它,并且要在addChildViews之后调用。
完成这两步,大家觉得能显示出来4个ViewController了吗?当然是不行的,因为我们还要把ViewController添加到scrollview中。但是,什么时候添加呢?如何添加?
我们发现,当我们第一次进入页面时,显示的是加载。
也就是说,当点击指示器按钮时,才会添加页面,然后初始化页面。所以,我们在scrollview的代理函数scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
函数中来添加ViewController。这个函数是当滑动动画结束的时候被调用,但是注意,这个滑动动画不是手动触发的滑动动画,而是setContentOffset:animated:
函数调用时动画完成后调用,手动拖拽scrollview是不会调用到这个函数的。那么我们就用scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
和setContentOffset:animated:
来配合使用,实现指示器按钮与scrollview的互动。
我们先来完成scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
函数。
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
{
//根据contentOffset的x值与scrollview的宽度的比值来确定当前滑动到了哪个view的内容范围
NSInteger index = scrollView.contentOffset.x / scrollView.width;
//上一步算出来的index就是我们需要显示的view的索引,从childViewControllers中取出对应的ViewController
UIViewController *vc = self.childViewControllers[index];
//设置取出来的vc的x和高度,填满scrollview
vc.view.x = scrollView.contentOffset.x;
vc.view.height = scrollView.height;
//最后添加vc到scrollview中
[scrollView addSubview:vc.view];
}
我们是在这个代理函数中添加的ViewController,那么如果程序刚启动,没有条件触发scrollview的动画,怎么显示第一个指示器对应的页面呢?这个简单,我们只需要在initScrollView
函数中,手动调用下scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
函数,传入创建的scrollview就好。
完成后,我们在指示器button对应的响应函数中调用setContentOffset:animated:
函数来调整scrollview的contentOffset,使scrollview滑动,触发scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
函数 。
- (void)btnClicked:(UIButton *)btn
{
//设置上次点击被disable的button为enable状态
self.indicatorDisableBtn.enabled = YES;
//当前点击的button为disable状态,好显示红色title
btn.enabled = NO;
//保存当前点击的button
self.indicatorDisableBtn = btn;
//设置红线的动画
[UIView animateWithDuration:0.2f animations:^{
self.indicatorLine.width = btn.titleLabel.width;
self.indicatorLine.centerX = btn.centerX;
}];
//添加滑动scrollview,点击button后scrollview跟着滑动到相应位置
//通过选中的button的tag值来判断现在选择的是第几个button,然后根据tag值决定需要滚动几个view的宽度
CGPoint offset = self.contentScrollView.contentOffset;
offset.x = btn.tag * self.contentScrollView.width;
//这里设置了animated参数为YES,在自动滚动scrollview的动画完成时会调用scrollViewDidEndScrollingAnimation
[self.contentScrollView setContentOffset:offset animated:YES];
}
这下,我们点击指示器的button时,scrollview就能改变view了。
接下来最后一步,实现手动滑动scrollview时更改scrollview内容,并且改变指示器位置。
//滑动scrollview时更改content
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
NSInteger index = scrollView.contentOffset.x / scrollView.width;
UIButton *btn = self.indicatorView.subviews[index];
//手动调用button的响应函数以便在拖拽scrollview时button跟着变化,以实现不同操作的相同结果
[self btnClicked:btn];
//当点击到的button对应的view没有添加到scrollview中时,手动调用下scrollViewDidEndScrollingAnimation函数来滚动scrollview并创建子视图。
[self scrollViewDidEndScrollingAnimation:scrollView];
}
完成后,看看运行结果
滑动scrollview后,界面切换了,并且指示器也跟着动了。