在介紹該框架之前,先來簡單說下父子控制器的知識點:
父子控制器:
若一個控制器通過addChildViewController:
方法添加多個控制器,被添加的控制器稱為子控制器
,添加多個子控制器的控制器稱為父控制器
。
使用原則: 如果兩個控制器的view是父子關系(不管是直接還是間接的父子關系),那么這兩個控制器也應該為父子關系,即如果A控制器的view添加到B控制器的view上,那么A控制器必須成為B控制器的子控制器
使用場景:
1.導航欄push
或者pop
到控制器的時候
[self.navigationController pushViewController:vc animated:YES];
系統(tǒng)首先會去判斷下self是否是導航控制器的子控制器,如果不是則判斷self的父控制器是否是導航控制器的子控制器,直到沒有父控制器為止,如果都不是導航控制器的子控制器則self.navigationController
為nil
2.Modal
到一個控制器的時候
[self dismissViewControllerAnimated:YES completion:nil];
原理同上,系統(tǒng)會判斷當前方法的調用者是否是被modal
出來的,如果不是則判斷父控制器是否被modal
出來的
ZPSegmentBar 該框架分為OC和Swfit兩個版本:
點擊前往Swift版本 點擊前往OC版本
該框架的主要功能包括兩部分:
1. 模仿今日頭條或者是網易新聞 NavigationBar 效果,效果圖如下:
集成該框架的主要步驟:
1. 導入頭文件 import ZPSegmentBar
2. 實例化ZPStyle
,并且傳入我們需要的樣式,例如:
var style = ZPStyle()
style.isScrollEnabled=true; //標題是否可以滾動,默認為true;
style.isShowCover = true //標題是否顯示遮蓋,默認為true;
style.isShowBottomLine=true //標題下方是否顯示BottomLine,默認為true;
style.isNeedScale=true //標題文字是否縮放,默認為true;
.
.
.
通過配置我們需要的樣式可以輕松的實現(xiàn)遮蓋
文字縮放
下劃線
文字顏色變化
等樣式.
3. 實例化 ZPSegmentBarView
,并且傳入所需要的參數
let segmentView = ZPSegmentBarView(frame: frame, titles: titles, style: style, childVcs: childVcs, parentVc: self)
4. 將創(chuàng)建好的 ZPSegmentBarView
添加到當前View中即可
view.addSubview(segmentView)
2. 封裝了一個表情鍵盤或者是禮物鍵盤,效果圖如下:
集成該功能的主要步驟:
1. 和上面的步驟一樣,導入頭文件 import ZPSegmentBar
2. 和上面的步驟一樣,實例化ZPStyle
,并且傳入我們需要的樣式,例如:
var style = ZPStyle()
style.isScrollEnabled=false; //標題是否可以滾動,默認為true;
style.isShowCover = false //標題是否顯示遮蓋,默認為true;
style.isShowBottomLine=true //標題下方是否顯示BottomLine,默認為true;
style.isNeedScale=true //標題文字是否縮放,默認為true;
.
.
.
3. 實例化ZPPageBarLayout
布局,并且傳入我們需要的樣式,例如:
let layout = ZPPageBarLayout()
layout.sectionInset = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
layout.minimumLineSpacing=10 //行距
layout.minimumInteritemSpacing=10 //item之間的間距
layout.columns=8 //列數
layout.rows = 3 //行數
4. 實例化ZPPageBarView
,并且傳入我們需要的參數,設置數據源代理,注冊cell
let pageBarView = ZPPageBarView(frame: frame, titles: titles, style: style, layout: layout)
pageBarView.dataSource=self //設置數據源代理,并且實現(xiàn)數據源方法
pageBarView.registerCell(UICollectionViewCell.self, reusableIdentifier: kCollectionViewCellID)
view.addSubview(pageBarView)
5.實現(xiàn)數據源方法
extension ViewController : ZPPageBarViewDataSource
{
func numberOfSections(in pageBarView: ZPPageBarView) -> Int {
return 4
}
func pageBarView(_ pageBarView: ZPPageBarView, numberOfItemsInSection section: Int) -> Int {
if section == 0 {
return 61
} else if section == 1 {
return 18
} else if section == 2 {
return 40
} else {
return 18
}
}
func pageBarView(_ pageBarView: ZPPageBarView, collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: kCollectionViewCellID, for: indexPath)
cell.backgroundColor = UIColor.randomColor()
return cell
}
}
注意
如果是導航控制器,我們需要在集成的View中 設置 automaticallyAdjustsScrollViewInsets=false
Installation
ZPSegmentBar is available through CocoaPods. To install
it, simply add the following line to your Podfile:
pod 'ZPSegmentBar', '~> 0.1.3'
后續(xù)糾錯過程
在使用的過程中我發(fā)現(xiàn)如果拖動的特別快會出現(xiàn)一些問題,如下圖:
經過排查發(fā)現(xiàn)在
ScrollView
的代理方法scrollViewDidScroll
中計算progress
的過程中有問題:
//左側滑動
if contentOffsetX > startOffsetX {
sourceIndex = Int(contentOffsetX / collectionWidth)
targetIndex = sourceIndex + 1
progress = (contentOffsetX - startOffsetX) / collectionWidth
print("progress:\(progress)")
if((contentOffsetX - startOffsetX)==collectionWidth)
{
progress = 1
targetIndex=sourceIndex
}
}
打印結果:
progress:0.621333333333333
progress:0.717333333333333
progress:0.805333333333333
progress:0.874666666666667
progress:0.932
progress:0.978666666666667
progress:1.05466666666667
progress:1.16133333333333
progress:1.28266666666667
progress:1.40666666666667
progress:1.532
progress:1.63866666666667
progress:1.73333333333333
progress:1.80933333333333
progress:1.88133333333333
progress:1.93733333333333
progress:1.98266666666667
可以發(fā)現(xiàn)在拖動特別快的時候progress
的值都已經超過1
了,改成下面這句就可以了:
progress = CGFloat(scrollView.contentOffset.x).truncatingRemainder(dividingBy: CGFloat(collectionWidth)) / CGFloat(collectionWidth)
通過truncatingRemainder
方法我們可以計算出兩個CGFloat
的取余運算