很久不寫簡書了,除了懶之外也肯定不能說項目很緊工作很忙.
今天更新一個很久之前寫過的分頁加載控制器,為什么要更新這個分頁加載這么常見的多如牛毛的輪子...主要是現(xiàn)在幾個主流 APP 都有關(guān)于這個分頁滑動效果的實現(xiàn),我見過的有:京東,微博,還有愛奇藝,其他的暫時沒發(fā)現(xiàn)哈.
基本效果:
更新后的主要滑動效果如下:
傳送門: Github
(Github上的 readme 并沒有更新,看簡書這里就行.)
對于實現(xiàn)以及更多的樣式感興趣的話可以繼續(xù)往下看.
主要實現(xiàn):
以上是一些基本效果的實現(xiàn).大體就是分頁條的下劃線隨著滑動手勢的執(zhí)行所實現(xiàn)的一個稍微有點酷的動畫效果.其實實現(xiàn)起來也不麻煩.只要注意切分滑動狀態(tài),就可以根據(jù)不同狀態(tài)下的滑動現(xiàn)象很容易分析出實現(xiàn)思路.
最主要的過程就是,將滑動的過程切分為:左滑和右滑 兩個部分,再分別將左滑和右滑兩個部分切分為:前半部分下劃線長度↑(增加)和后半部分下劃線長度↓(減少). 總共四中狀態(tài),分別針對四中狀態(tài)監(jiān)聽
- scrollViewDidScroll:
做不同的長度處理,同時在這個過程中,動態(tài)的去修改下劃線的 center.x 位置就能夠?qū)崿F(xiàn)這個效果.
上一下實現(xiàn)這個過程的核心代碼:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
CGFloat changedW = _pageCellW*2*fabs(x-ScreenW*index) / ScreenW;
_line.frame = CGRectMake(0, _pageBarHeight-_lineHeight, _lineWidth+changedW, _lineHeight);
CGFloat centerX;
if (toLeft) {
if ((x-ScreenW*index) > 0) { //未過半屏: 過半屏之后因為index = (x + ScreenW*0.5) / ScreenW; 所以 index 值會+1
centerX = index * _pageCellW + _pageCellW/2 + changedW/2;
}else{ //劃過半屏
centerX = index * _pageCellW + _pageCellW/2 - changedW/2;
}
}else{
if ((x-ScreenW*index) < 0) { //未過半屏
centerX = index * _pageCellW + _pageCellW/2 - changedW/2;
}else{ //劃過半屏
centerX = index * _pageCellW + _pageCellW/2 + changedW/2;
}
}
_line.center = CGPointMake(centerX, _pageBarHeight-_lineHeight/2);
}
}
擴展了非常多的實用性的功能,調(diào)用方式有以下幾種都可以實現(xiàn):
/**
創(chuàng)建分頁控制器 : 自動創(chuàng)建全部控制器(方式一)
@param titlesArray 標(biāo)題數(shù)組
@param controllers 控制器數(shù)組
@param onNavigationBar 分頁欄是否放在控制器導(dǎo)航欄上
@return 棧頂控制管理器
*/
- (instancetype)initWithTitles:(NSArray *)titlesArray controllers:(NSArray *)controllers onNavigationBar:(BOOL)onNavigationBar;
/**
* 創(chuàng)建分頁控制器 : 滑動到相應(yīng) index 位置時才去創(chuàng)建相應(yīng)控制器,此方式不太好傳參(方式二)
*
* @param titlesArray 標(biāo)題數(shù)組
* @param controllersClass 要創(chuàng)建的控制器類名數(shù)組
* @param onNavigationBar 分頁欄是否放在控制器導(dǎo)航欄上
* @return 棧頂控制管理器
*/
- (instancetype)initWithTitles:(NSArray *)titlesArray controllersClass:(NSArray *)controllersClass onNavigationBar:(BOOL)onNavigationBar;
使用:
可以用方式1初始化,傳進去實例化好的控制器對象集合,也可以用方式2初始化,傳進去未實例化的控制器類集合,等滑動到相應(yīng)位置時再去動態(tài)實例化,可以自由選擇實例化方式,選擇是否將分頁條加載于導(dǎo)航條上,并且已經(jīng)做了關(guān)于 iPhone X 的適配.
同時,實際調(diào)用的時候,可以直接push-->XXPageMenuController, 或者將PageMenu添加到 parentViewController/view, 套一層parentViewController以實現(xiàn)導(dǎo)航條上更全面的設(shè)置,如果項目有需求的話.
if (indexPath.section == 0) {
XXPageMenuController *pageMenuController = nil;
switch (indexPath.row) {
case 0:
{
NSMutableArray *controllersClass = [NSMutableArray array];
[titles enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
[controllersClass addObject:[PageCell2Controller class]];
}];
pageMenuController = [[XXPageMenuController alloc] initWithTitles:titles controllersClass:controllersClass onNavigationBar:YES];
}
break;
case 1:
{
NSMutableArray *controllers = [NSMutableArray array];
[titles enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
[controllers addObject:[PageCell1Controller new]];
}];
pageMenuController = [[XXPageMenuController alloc] initWithTitles:titles controllers:controllers onNavigationBar:NO];
pageMenuController.titleColor = [UIColor whiteColor];
pageMenuController.pageBarBgColor = [UIColor grayColor];
pageMenuController.pageBarHeight = 44;
pageMenuController.lineColor = [UIColor orangeColor];
}
break;
case 2:
{
pageMenuController = [[XXPageMenuController alloc] initWithTitles:titles2 controllersClass:@[[PageCell2Controller class],[PageCell2Controller class],[PageCell2Controller class],[PageCell2Controller class]] onNavigationBar:YES];
}
break;
default:
{
pageMenuController = [[XXPageMenuController alloc] initWithTitles:titles2 controllersClass:@[[PageCell1Controller class],[PageCell1Controller class],[PageCell1Controller class],[PageCell2Controller class]] onNavigationBar:NO];
}
break;
}
[self.navigationController pushViewController:pageMenuController animated:YES];
}else{
switch (indexPath.row) {
case 0:
[self.navigationController pushViewController:[Parent1Controller new] animated:YES];
break;
case 1:
[self.navigationController pushViewController:[Parent2Controller new] animated:YES];
break;
case 2:
[self.navigationController pushViewController:[Parent3Controller new] animated:YES];
break;
default:
[self.navigationController pushViewController:[Parent4Controller new] animated:YES];
break;
}
}
基本效果實現(xiàn)以后,除了原有的一些可設(shè)置的屬性:
/** 分頁條高度 */
@property(nonatomic, assign) CGFloat pageBarHeight;
/** 分頁條背景色 */
@property (nonatomic,strong) UIColor *pageBarBgColor;
/** 下滑線顏色 */
@property (nonatomic,strong) UIColor *lineColor;
/** 下滑線高度 */
@property (nonatomic,assign) CGFloat lineHeight;
/** 標(biāo)題顏色 */
@property (nonatomic,strong) UIColor *titleColor;
/** 標(biāo)題字體 */
@property (nonatomic,strong) UIFont *titleFont;
之外,還對這個小工具做了一些新的,在項目中可能會用到的優(yōu)化:
/** 標(biāo)題選中顏色(可不設(shè)置) */
@property (nonatomic,strong) UIColor *titleSelectedColor;
/** 下劃線長度取值類型 */
@property (nonatomic,assign) LineWidthType lineWidthType;
/** 下劃線在條目切換時的動態(tài)表現(xiàn)類型 */
@property (nonatomic,assign) LineScrollType lineScrollType;
/**
下劃線長度取值類型
- LineWidthTypeStaticShort: 靜態(tài)短長度,取個固定短值
- LineWidthTypeStaticLong: 靜態(tài)長度,根據(jù)總長度/數(shù)量
- LineWidthTypeDynamic: 動態(tài)長度,根據(jù)文字長度
*/
typedef NS_ENUM(NSInteger, LineWidthType) {
LineWidthTypeStaticShort = 0,
LineWidthTypeStaticLong,
LineWidthTypeDynamic,
};
/**
下劃線在條目切換時的動態(tài)表現(xiàn)類型
- LineScrollTypeDynamicAnimation: 即時的下劃線動態(tài)動畫
- LineScrollTypeFinishedAnimation: 完成后的下劃線動態(tài)動畫
- LineScrollTypeFinishedLinear: 完成后的下劃線線性動畫
- LineScrollTypeDynamicLinear: 即時的下劃線線性動畫(先不做了,實用性完全被LineScrollTypeDynamicAnimation替代了...)
*/
typedef NS_ENUM(NSInteger, LineScrollType) {
LineScrollTypeDynamicAnimation = 0,
LineScrollTypeFinishedAnimation,
LineScrollTypeFinishedLinear,
};
增加了默認選中位置的設(shè)置:
/** 默認選擇的 index 位置 ,默認值為0*/
- (void)moveToDefaultIndex:(NSInteger)index;
同時也保留了原有的常用的下劃線滑動方式:
增加了在滑動即將結(jié)束時- scrollViewDidEndDecelerating:
處理的新動畫效果(這里用了隨機數(shù)0/1去 push 的這一條):
實際的使用方式 demo 里都寫的很詳細,這里是最后留下的傳送門,如果您有興趣使用這個分頁條,歡迎使用并感謝您留個贊.
傳送門: Github
(Github上的 readme 并沒有更新,看簡書這里就行.)
未完待續(xù):
*下一版計劃在分頁條上增加一個按鈕的顯示方式,一個圖標(biāo)一個標(biāo)題這樣子.
結(jié)尾:
- 如果發(fā)現(xiàn)bug和什么任何問題涂臣,請與我聯(lián)系族铆。
- 有好的意見或建議材鹦,可以聯(lián)系我茉兰。