我們經(jīng)常會(huì)用到各種分欄,比如:
第一張圖是app store排行榜的分欄偷线,它最普通的分欄亥曹,使用系統(tǒng)的UISegmentControl即可實(shí)現(xiàn)(是不是發(fā)現(xiàn)這個(gè)導(dǎo)航條很高媳瞪,或者說UISegmentControl與導(dǎo)航條看起來是一個(gè)整體驶悟,我之前研究了一下,實(shí)現(xiàn)方法在這里:App Store 排行榜導(dǎo)航條實(shí)現(xiàn))材失。
第二張圖是知乎"通知"模塊導(dǎo)航實(shí)現(xiàn)痕鳍,用過知乎的小伙伴,如果細(xì)心的話會(huì)發(fā)現(xiàn)當(dāng)左右滾動(dòng)通知模塊時(shí)龙巨,頂部的分段控件會(huì)發(fā)生如下變化:
- 分段控件的標(biāo)題顏色變化笼呆,選中則為黑色,未選中則為灰色
- 標(biāo)題底部有一根藍(lán)色的條旨别,選中那個(gè)標(biāo)題诗赌,藍(lán)色的條就會(huì)在哪個(gè)標(biāo)題下面
- 藍(lán)色的條在輕輕滑動(dòng)頁面時(shí),藍(lán)色的條也會(huì)跟隨滑動(dòng)秸弛,且?guī)в羞^度效果
- 藍(lán)色的條在跟隨滑動(dòng)時(shí)铭若,長度也會(huì)隨著文本的變化而變化洪碳,且?guī)в羞^度效果
我們平時(shí)的實(shí)現(xiàn),或者一些開源庫的實(shí)現(xiàn)一般只是做到了前面兩點(diǎn)叼屠,雖然功能都實(shí)現(xiàn)了瞳腌,但是用起來卻沒有絲滑般的感受啊??。所以強(qiáng)迫癥的我就研究了一下如何實(shí)現(xiàn)后兩點(diǎn)中提到的效果镜雨。
這里為了方便嫂侍,我使用了一個(gè)分段控件的開源庫:RKSwipeBetweenViewControllers。它很好的實(shí)現(xiàn)了前面兩點(diǎn)功能荚坞,而且想要實(shí)現(xiàn)后兩點(diǎn)的話直接修改它的代碼也是非常方便的挑宠。
我們先看一下第三點(diǎn)的效果如何實(shí)現(xiàn),我們需要在頁面滾動(dòng)時(shí)颓影,藍(lán)色的條跟隨滾動(dòng)各淀,所以需要不停的變化藍(lán)色條的坐標(biāo),因此關(guān)鍵代碼在UIScollView的代理scrollViewDidScroll:
中诡挂。
實(shí)現(xiàn)代碼如下:
-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGFloat percentX = (scrollView.contentOffset.x - CGRectGetWidth(scrollView.frame)) / CGRectGetWidth(scrollView.frame);//往左滑動(dòng)大于0碎浇,往右小于0(由于默認(rèn)偏移320)
NSLog(@"percentX:%f",percentX);
NSInteger currentPageIndex = self.currentPageIndex;
UIButton *curBtn = [[navigationView subviews] objectAtIndex:currentPageIndex];
CGFloat centerxOfSelectionBar = curBtn.center.x + percentX*_titleWidth;
selectionBar.center = CGPointMake(centerxOfSelectionBar, selectionBar.center.y);
}
首先說明一下,這里scrollview的contentOffset.x默認(rèn)偏移了320(即屏幕寬咆畏,我用的iPhone SE南捂,屏寬320)吴裤。切每切換一個(gè)頁面旧找,偏移都會(huì)被修改為320。
這里percentX
是一個(gè)偏移度麦牺,絕對(duì)值小于或等于1钮蛛。往左滑動(dòng)大于0,往右小于0剖膳。
這里我是通過藍(lán)色條的中心點(diǎn)來確定藍(lán)色條的位置的魏颓,centerxOfSelectionBar
是計(jì)算的藍(lán)色條的中心。而_titleWidth
是頂部標(biāo)題按鈕的寬度(這里標(biāo)題是用的按鈕吱晒,等寬)甸饱。
CGFloat centerxOfSelectionBar = curBtn.center.x + percentX*_titleWidth;
這行應(yīng)該比較好理解,看下面這張圖(不要夸我仑濒,我知道我畫的好O(∩_∩)O謝謝)
往左滑動(dòng)時(shí)叹话,藍(lán)色條的中心由1滑動(dòng)到2,1到2的間距正好是_titleWidth墩瞳,所以1到2任意一點(diǎn)的x坐標(biāo)就是1的x坐標(biāo)加上偏移的量驼壶,即上面代碼所示。
這樣就實(shí)現(xiàn)了第三點(diǎn)的效果喉酌。
至于第四點(diǎn)中提到的效果热凹,很明顯也是在同一個(gè)代理中實(shí)現(xiàn)泵喘,實(shí)現(xiàn)如下:
NSInteger currentPageIndex = self.currentPageIndex;
UIButton *curBtn = [[navigationView subviews] objectAtIndex:currentPageIndex];
NSInteger targetPage = percentX > 0 ? currentPageIndex+1:currentPageIndex-1;
if (targetPage >= 0 && targetPage < _buttonText.count)
{
UIButton *targetBtn = [[navigationView subviews] objectAtIndex:targetPage];
CGSize sizeOrigin = MB_TEXTSIZE(curBtn.currentTitle, [UIFont systemFontOfSize:FONT_SIZE_16]);
CGFloat lengthOrigin = sizeOrigin.width;
CGSize sizeTarget = MB_TEXTSIZE(targetBtn.currentTitle, [UIFont systemFontOfSize:FONT_SIZE_16]);
CGFloat lengthTarget = sizeTarget.width;
CGFloat selctionBarLength = lengthTarget + (lengthOrigin - lengthTarget)*(1-ABS(percentX));
selectionBar.frame = CGRectMake(selectionBar.frame.origin.x, selectionBar.frame.origin.y, selctionBarLength, selectionBar.frame.size.height);
}
MB_TEXTSIZE是MBProgress中定義的計(jì)算文字尺寸的宏定義,我直接拷過來用的般妙。
上面的代碼我想大部分應(yīng)該都容易看明白纪铺,就只有下面這行有點(diǎn)麻煩:
CGFloat selctionBarLength = lengthTarget + (lengthOrigin - lengthTarget)*(1-ABS(percentX));
我來說明一下:
如上圖所示,假設(shè)a位置的標(biāo)題長度為a股冗,b位置長度為b霹陡,由a滑動(dòng)到b,L是目標(biāo)長度,即最后停留位置藍(lán)色條的長度:
- 如果a>b,L1 = b + (a - b)*(1-ABS(percentX))
- 如果b>a,L2 = b - (b - a)*(1-ABS(percentX))
對(duì)比一下會(huì)發(fā)現(xiàn)止状,L1 與 L2 是相等的烹棉,所以公式可以簡化為
L = b - (b - a)*(1-ABS(percentX))
demo地址在這:SegmentControlDemo,隨意下載怯疤。
如果本文對(duì)你有用浆洗,給個(gè)??吧,謝謝~