一、构思需求
日常开发中,我们经常需要标签栏来展示不同的视图。点击每个标签切换不同的页面,像我们平时用的头条、京东分类标签,都是用标签栏来进行内容分类导航。接下来我们来实现一下普通的一个标签栏。
一个标签视图主要功能有:
1、多个标签可以滚动
2、每个标签可以点击
二、实现
当我们从需求的角度去考虑问题,逻辑就很清晰。确定了控件的选择,我们接下来要做的就是根据需求确定下来的逻辑点去发散思考。
1、既然多个标签可以滚动,那我们首选的控件必然是UIScrollView
(1)、确定scrollView的contentSize
(2)、scrollView上的button的frame
2、既然标签可以点击,直接上UIButton
(1)、如何让button在scrollView上滚动(滚动方式如何实现):
1、确定选择的标签停留的位置:(以屏幕中间为例)
CGFloat centerWidth = scrollView.bounds.size.width/2;
2、标签可能出现的位置:(逻辑条件)
CGFloat halfWidth = ((index+1) *2-1) *0.5*viewWidth;
(viewWidth是每个标签,也就是每个button的宽度,index就是我们当前要移动的 button索引)
可以根据上述分析去思考实现方式:其中主要的点在于逻辑条件,逻辑条件要清晰、全面才能使我们代码编写思路是正确的。
一个标签什么时候才会开始滚动?我们从左到右观察会发现:如果button标签中心位置的水平距离(halfWidth)大于选择标签停留的位置(屏幕中点centerWidth),button标签需要向左移动到屏幕中点。这里有个问题:是不是满足此条件的标签都要向左移动到屏幕中点呢?如果是最右边的那个标签显然不能移动到屏幕中点。
if (halfWidth > centerWidth){
//计算button标签中心位置与屏幕中点位置的偏移量
CGFloat disWidth = halfWidth - centerWidth;
[UIView animateWithDuration:0.2 animations:^{
self->scrollView.contentOffset=CGPointMake(disWidth,0);
}];
}else{
1、跟着上面的思路直接写else,也就是button标签的中心位置在屏幕中点左边,那我们就不用移动了。
[UIView animateWithDuration:0.2 animations:^{
self->scrollView.contentOffset=CGPointMake(0,0);
}];
}
这样做会有bug,原因是因为上面抛出的问题,如果是最右面的标签我是不用移动到中点也不能移动到中点。
我们仔细考虑就会知道还有一个条件我们忽略了,那就是scrollView向左移动的偏移量必然小于或者等于contentSize的宽度减去屏幕宽度才能移动到屏幕中心,else根本向左移动不到屏幕中点。所以:
if(halfWidth > centerWidth)
{
CGFloatdisWidth = halfWidth - centerWidth;
if(disWidth <= totolWidth -ScreenWidth) {
[UIView animateWithDuration:0.2 animations:^{
self->scrollView.contentOffset=CGPointMake(disWidth,0);
}];
}else{
[UIView animateWithDuration:0.2 animations:^{
self->scrollView.contentOffset=CGPointMake(totolWidth -ScreenWidth,0);
}];
}
}else{
[UIView animateWithDuration:0.2 animations:^{
self->scrollView.contentOffset=CGPointMake(0,0);
}];
}
这样我们就完成了标签的滚动范围控制。下面的布局和点击事件相信大家都非常熟悉了。我草 写的真垃圾。