首先,预览一下实现效果:
滚动标签条在应用中起到导航的功能,可将正文内容分成具体的内容模块,用户点击标签时相对应的内容视图同步切换,反之,滑动内容视图的页面时标签条也会跟随变换。ps.图中的label为自定义控件GYLabel,可达到点击时字体放大变色的效果,本文中就先不赘述。
为达到以上需求,实现方式如下:
主框架由两个scrollview组成:
1.滚动标题条smallScroll
2.对应于标题的内容视图bigScroll
==== 完成点击标签显示对应的内容视图====
a.滚动标题条绑定用户点击响应
滚动标题条的视图是由GYLabel组合而成的,每add一个子视图,配置tag属性,由0开始逐个递增;给每一个标签添加手势:
addGestureRecognizer:[ [UITapGestureRecognizer alloc]
initWithTarget:self action:@selector(lblClick:) ]
响应方法lblClick中拿到点击视图,根据标签的tag值算出大的滚动内容视图的位移值,这样可做到标签与内容视图以及用户交互动作的三者绑定。
ps.不要忘记label.userInteractionEnabled = YES
-(void)lblClick:(UITapGestureRecognizer*)recognizer
//点击标签时内容视图滑动到指定的坐标,并且带动画效果
{ [self.bigScroll setContentOffset:
CGPointMake(recognizer.view.tag*self.bigScroll.bounds.size.width, 0)
animated:YES]; }
b.显示bigScroll的内容视图
分析一下:致使bigScroll发生滑动的有可能是用户点击了标签或者直接滑动屏幕,而在这两种情况下都会调用的方法应该是系统的UIScrollViewDelegate中的委托响应方法。
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{ [self scrollViewDidEndScrollingAnimation:scrollView]; }
选用以上的委托代理响应顺序,在view停止滑动并且动画结束时调用,在方法中讲子控制器的view加载到bigScroll,子控制器的实例对象在viewDidLoad时机中已经生成。
此处用子控制器来完成是考虑到界面如果比较复杂,其相关设置可由子控制器去完成。
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView{
NSUInteger index=scrollView.contentOffset.x/self.bigScroll.bounds.size.width;
UIViewController* vc=self.childViewControllers[index];
vc.view.frame=scrollView.bounds;
[self.bigScroll addSubview:vc.view]; }
==== 手动滑动内容视图滚动标签条跟随变化====
因为是伴随着滑动时页面显示一起变化的,所以这部分的逻辑实现应该和页面生成是在同一个时机。
分析一下:用户的点击区域分成屏幕可视部分的左半边和右半边
a.如果点击的标签中心点的位置在左半边,则点击不发生位移;
b.如果点击的标签中心点的位置在右半边,则点击时标签水平位移到屏幕中心点;
c.需要考虑标签的最大水平位移距离(滚动标题条smallScroll内容视图超出屏幕部分的水平距离),如果位移到屏幕中心点的位移量大于最大水平位移距离,则此时的水平位移量应该设定为最大水平位移距离。
`
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView{
NSUInteger index=scrollView.contentOffset.x/self.bigScroll.bounds.size.width;
UILabel* label=self.smallScroll.subviews[index];
//中心点在左半边
CGFloat offsetx=label.center.x-self.smallScroll.bounds.size.width*0.5;
//最大水平位移距离
CGFloat offsetMax=
self.smallScroll.contentSize.width-self.smallScroll.bounds.size.width;
if (offsetx<0) {offsetx=0;}
else if(offsetx>offsetMax) {offsetx=offsetMax; }
[self.smallScroll setContentOffset:CGPointMake(offsetx, 0) animated:YES]; }
`