分頁控制器加載工具XXPageMenuController

很久不寫簡書了,除了懶之外也肯定不能說項目很緊工作很忙.

今天更新一個很久之前寫過的分頁加載控制器,為什么要更新這個分頁加載這么常見的多如牛毛的輪子...主要是現(xiàn)在幾個主流 APP 都有關(guān)于這個分頁滑動效果的實現(xiàn),我見過的有:京東,微博,還有愛奇藝,其他的暫時沒發(fā)現(xiàn)哈.

基本效果:

更新后的主要滑動效果如下:


donghua.gif

donghua1.gif

傳送門: 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;
donghua1.gif

同時也保留了原有的常用的下劃線滑動方式:


donghua1.gif

增加了在滑動即將結(jié)束時- scrollViewDidEndDecelerating: 處理的新動畫效果(這里用了隨機數(shù)0/1去 push 的這一條):

donghua1.gif

實際的使用方式 demo 里都寫的很詳細,這里是最后留下的傳送門,如果您有興趣使用這個分頁條,歡迎使用并感謝您留個贊.

傳送門: Github
(Github上的 readme 并沒有更新,看簡書這里就行.)

未完待續(xù):

*下一版計劃在分頁條上增加一個按鈕的顯示方式,一個圖標(biāo)一個標(biāo)題這樣子.

結(jié)尾:

  • 如果發(fā)現(xiàn)bug和什么任何問題涂臣,請與我聯(lián)系族铆。
  • 有好的意見或建議材鹦,可以聯(lián)系我茉兰。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末燃辖,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖陷虎,帶你破解...
    沈念sama閱讀 218,607評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件凿掂,死亡現(xiàn)場離奇詭異塘安,居然都是意外死亡萝究,警方通過查閱死者的電腦和手機栽连,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來叙淌,“玉大人茂洒,你說我怎么就攤上這事督勺。” “怎么了赞辩?”我有些...
    開封第一講書人閱讀 164,960評論 0 355
  • 文/不壞的土叔 我叫張陵屉佳,是天一觀的道長体箕。 經(jīng)常有香客問我,道長玉雾,這世上最難降的妖魔是什么壁涎? 我笑而不...
    開封第一講書人閱讀 58,750評論 1 294
  • 正文 為了忘掉前任担汤,我火速辦了婚禮叔营,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己景描,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,764評論 6 392
  • 文/花漫 我一把揭開白布再扭。 她就那樣靜靜地躺著柠傍,像睡著了一般。 火紅的嫁衣襯著肌膚如雪从媚。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,604評論 1 305
  • 那天,我揣著相機與錄音了赵,去河邊找鬼项玛。 笑死硅则,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的困介。 我是一名探鬼主播大审,決...
    沈念sama閱讀 40,347評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼座哩!你這毒婦竟也來了徒扶?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,253評論 0 276
  • 序言:老撾萬榮一對情侶失蹤根穷,失蹤者是張志新(化名)和其女友劉穎姜骡,沒想到半個月后导坟,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,702評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡圈澈,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,893評論 3 336
  • 正文 我和宋清朗相戀三年惫周,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片康栈。...
    茶點故事閱讀 40,015評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡递递,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出啥么,到底是詐尸還是另有隱情漾狼,我是刑警寧澤,帶...
    沈念sama閱讀 35,734評論 5 346
  • 正文 年R本政府宣布饥臂,位于F島的核電站逊躁,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏隅熙。R本人自食惡果不足惜稽煤,卻給世界環(huán)境...
    茶點故事閱讀 41,352評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望囚戚。 院中可真熱鬧酵熙,春花似錦、人聲如沸驰坊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,934評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽拳芙。三九已至察藐,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間舟扎,已是汗流浹背分飞。 一陣腳步聲響...
    開封第一講書人閱讀 33,052評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留睹限,地道東北人譬猫。 一個月前我還...
    沈念sama閱讀 48,216評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像羡疗,于是被迫代替她去往敵國和親染服。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,969評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 1叨恨、通過CocoaPods安裝項目名稱項目信息 AFNetworking網(wǎng)絡(luò)請求組件 FMDB本地數(shù)據(jù)庫組件 SD...
    陽明先生_X自主閱讀 15,982評論 3 119
  • 閃電 一次又一次地穿透了 合攏的眼簾柳刮, 隨后的雷聲 震聾了 有些遲鈍的耳膜, 如注的夜雨啊 沒完沒了 還是沒完沒了...
    SS中閱讀 623評論 0 6
  • 今天這一天就豐富了,搞的我在作業(yè)關(guān)門之前是寫不完的〕涎牵現(xiàn)在已經(jīng)是零點了晕换。 昨天晚上交完作業(yè)以后一直沒睡著,到...
    閑度閱讀 199評論 2 1
  • CPU 224編址范圍SM0.0 ~SM179.7站宗,共180個字節(jié)闸准。其中SM0.0~SM29.7的30個字節(jié)為只讀...
    王博超0321閱讀 1,111評論 0 0