仿網(wǎng)易新聞Navbar

效果圖:


網(wǎng)易導(dǎo)航條.gif

在項(xiàng)目中有類似的需求齿梁,仿網(wǎng)易新聞Navbar主要借助UIScrollview與 addChildViewController 實(shí)現(xiàn)這個(gè)效果。
在滾動(dòng)時(shí)候有可能會(huì)有兩個(gè)需求

  • 點(diǎn)擊item 滾動(dòng)到中間
  • 在超出屏幕時(shí)點(diǎn)擊才發(fā)生滾動(dòng)

所以在自定義SegmentControl的時(shí)候 定義一個(gè)枚舉:

typedef enum : NSUInteger {
    LXSegmentedControlTypeCenterScroll, // 中心滾動(dòng)風(fēng)格
    LXSegmentedControlTypeEndScroll, // 超出屏幕滾動(dòng)風(fēng)格
} LXSegmentedControlScrollType;  // 默認(rèn)為滾動(dòng)風(fēng)格

第一步 定義一個(gè)LXSegmentControl 繼承于UIScrollview肮蛹。接口中暴露以下屬性勺择,有類方法構(gòu)造以及對(duì)象方法構(gòu)造,滾動(dòng)類型選擇伦忠,接口方法中已經(jīng)傳入代理UIViewController省核。

@protocol LXSegmentControlDelegate<NSObject>
-(void)LXSegmentControl:(LXSegmentControl *)segmentControl didSelectBtnAtIndex:(NSInteger)index;
@end;
@interface LXSegmentControl : UIScrollView
//對(duì)象方法創(chuàng)建 LXSegmentControl
-(instancetype)initWithFrame:(CGRect)frame delegate:(id <LXSegmentControlDelegate>)delegate titleArr:(NSArray *)titleArr;
//類方法創(chuàng)建 LXSegmentControl
+(instancetype)segmentControlWithFrame:(CGRect)frame delegate:(id <LXSegmentControlDelegate>)delegate titleArr:(NSArray *)titleArr;

@property(nonatomic,weak)id <LXSegmentControlDelegate> SeDelegate;

@property(nonatomic,assign)LXSegmentedControlScrollType scrollType;

///** 滾動(dòng)Conrolller的時(shí)候 SegmentControl需要做的處理 */
- (void)titleBtnSelectedWithScrollView:(UIScrollView *)scrollView;

@end

第二部 根據(jù)傳入的title 數(shù)組創(chuàng)建button 然后設(shè)置UIScrollview的內(nèi)容大小。button的大小通過API計(jì)算出字符串的長度昆码,然后設(shè)置margin气忠。

for (NSUInteger i  = 0; i <_title_Arr.count; i++) {
        
        self.title_btn =[UIButton buttonWithType:UIButtonTypeCustom];
        _title_btn.titleLabel.font = LXFont(btn_fondOfSize);
        _title_btn.tag = i;
        
        //計(jì)算內(nèi)容的size
        CGSize buttonSize =[self sizeWithText:_title_Arr[i] font:LXFont(btn_fondOfSize) maxSize:CGSizeMake(MAXFLOAT, button_H)];
        //計(jì)算內(nèi)容的寬度
        CGFloat button_W = 2 *btn_Margin + buttonSize.width;
        _title_btn.frame = CGRectMake(button_X, button_Y, button_W, button_H);
        [_title_btn setTitle:_title_Arr[i] forState:UIControlStateNormal];
        [_title_btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
        [_title_btn setTitleColor:[UIColor redColor] forState:UIControlStateSelected];
        
        //計(jì)算每個(gè)button的 X 值
        button_X = button_X + button_W;
        //點(diǎn)擊事件
        [_title_btn addTarget:self action:@selector(buttonAction:) forControlEvents:UIControlEventTouchUpInside];
        
        //默認(rèn)選中第0 個(gè)button
        if (i == 0) {
            [self buttonAction:_title_btn];
        }
        //存入所有的 title_btn
        [self.titleBtn_mArr addObject:_title_btn];
        [self addSubview:_title_btn];
        
    }
    
    //計(jì)算 scrollview 的寬度
    
    UIButton *lastButton = self.titleBtn_mArr.lastObject;
    CGFloat scrollViewWidth = CGRectGetMaxX(lastButton.frame);
    self.contentSize = CGSizeMake(scrollViewWidth, self.height);

最關(guān)鍵的處理在于 處理button 的點(diǎn)擊方法 在點(diǎn)擊時(shí)候處理contentoffset,是在點(diǎn)擊屏幕最后一個(gè)按鈕然后滾動(dòng)UIScrollview赋咽,還是選擇居中模式旧噪。

#pragma mark - - - 按鈕的點(diǎn)擊事件
- (void)buttonAction:(UIButton *)sender
{
    [self titleBtnSelectededCenter:sender];
    
    // 2、代理方法實(shí)現(xiàn)
    NSInteger index = sender.tag;
    
    if ([self.SeDelegate respondsToSelector:@selector(LXSegmentControl:didSelectBtnAtIndex:)]) {
        
        [self.SeDelegate LXSegmentControl:self didSelectBtnAtIndex:index];
    }
    
    //3 脓匿、 改變指示器的位置
    [self titleBtnSelected:sender];
}

/** 滾動(dòng)標(biāo)題選中居中 */
- (void)titleBtnSelectededCenter:(UIButton *)centerBtn {
  
    
    switch (self.scrollType) {
        case LXSegmentedControlTypeCenterScroll:
            
            [self centerScroll:centerBtn];
            
            break;
        case LXSegmentedControlTypeEndScroll:
            
            [self endScroll:centerBtn];
            
        default:
            break;
    }
}
-(void)centerScroll:(UIButton *)centerBtn
{
     //計(jì)算偏移量
        CGFloat offsetX = centerBtn.center.x - Device_Width * 0.5;
    
        if (offsetX < 0) offsetX = 0;
    
        // 獲取最大滾動(dòng)范圍
        CGFloat maxOffsetX = self.contentSize.width - Device_Width;
    
        if (offsetX > maxOffsetX) offsetX = maxOffsetX;
    
        // 滾動(dòng)標(biāo)題滾動(dòng)條
        [self setContentOffset:CGPointMake(offsetX, 0) animated:YES];
}

-(void)endScroll:(UIButton *)centerBtn
{
    CGFloat offsetX;
    
    if (CGRectGetMaxX(centerBtn.frame) >= Device_Width) {
        
        offsetX = CGRectGetMaxX(centerBtn.frame) - Device_Width;
        
        if (centerBtn.tag <[_title_Arr count]-1) {
            offsetX = offsetX + centerBtn.frame.size.width;
        }
    }else
    {
        offsetX = 0 ;
    }
    [self setContentOffset:CGPointMake(offsetX, 0) animated:YES];

}

接口中需要暴露 一個(gè)方法當(dāng)我們滾動(dòng)子控制器的時(shí)候item 需要作出的改變

/** 標(biāo)題選中顏色改變以及指示器位置變化 */
- (void)titleBtnSelectedWithScrollView:(UIScrollView *)scrollView {
    // 1淘钟、計(jì)算滾動(dòng)到哪一頁
    NSInteger index = scrollView.contentOffset.x / scrollView.frame.size.width;
    
    // 2、把對(duì)應(yīng)的標(biāo)題選中
    UIButton *selectedBtn = self.titleBtn_mArr[index];
    
    // 3陪毡、滾動(dòng)時(shí)米母,改變標(biāo)題選中
    [self titleBtnSelected:selectedBtn];
}

接下來是ViewControll中的處理

實(shí)現(xiàn)LXSegmentControl的代理

-(void)LXSegmentControl:(LXSegmentControl *)segmentControl didSelectBtnAtIndex:(NSInteger)index
{
    // 1 計(jì)算滾動(dòng)的位置
    CGFloat offsetX = index * self.view.frame.size.width;
    self.mainScrollView.contentOffset = CGPointMake(offsetX, 0);
    
    // 2.給對(duì)應(yīng)位置添加對(duì)應(yīng)子控制器
    [self showVc:index];
}

當(dāng)我們?cè)谔砑幼右晥D的view的時(shí)候判斷是不是該控制器的視圖已經(jīng)進(jìn)行了懶加載

vc.isViewLoaded

// 顯示控制器的view
- (void)showVc:(NSInteger)index {
    
    CGFloat offsetX = index * self.view.frame.size.width;
    
    UIViewController *vc = self.childViewControllers[index];
    
    // 判斷控制器的view有沒有加載過,如果已經(jīng)加載過,就不需要加載
    if (vc.isViewLoaded) return;
    vc.view.backgroundColor =  LBRandomColor;
    [self.mainScrollView addSubview:vc.view];
    vc.view.frame = CGRectMake(offsetX, 0, self.view.frame.size.width, self.view.frame.size.height);
}

最后 處理在滑動(dòng)切換子控制器的時(shí)候需要LXSegmentControl需要做的處理

#pragma mark - UIScrollViewDelegate
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
    
    // 計(jì)算滾動(dòng)到哪一頁
    NSInteger index = scrollView.contentOffset.x / scrollView.frame.size.width;
    
    // 1.添加子控制器view
    [self showVc:index];
    
    // 2.把對(duì)應(yīng)的標(biāo)題選中 接口中已經(jīng)暴露
    [self.segmentControl titleBtnSelectedWithScrollView:scrollView];
}

demo地址 兩種Navbar滾動(dòng)類型

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市毡琉,隨后出現(xiàn)的幾起案子铁瞒,更是在濱河造成了極大的恐慌,老刑警劉巖桅滋,帶你破解...
    沈念sama閱讀 222,464評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件慧耍,死亡現(xiàn)場離奇詭異,居然都是意外死亡虱歪,警方通過查閱死者的電腦和手機(jī)蜂绎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,033評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來笋鄙,“玉大人师枣,你說我怎么就攤上這事∠袈洌” “怎么了践美?”我有些...
    開封第一講書人閱讀 169,078評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵洗贰,是天一觀的道長。 經(jīng)常有香客問我陨倡,道長敛滋,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,979評(píng)論 1 299
  • 正文 為了忘掉前任兴革,我火速辦了婚禮绎晃,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘杂曲。我一直安慰自己庶艾,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,001評(píng)論 6 398
  • 文/花漫 我一把揭開白布擎勘。 她就那樣靜靜地躺著咱揍,像睡著了一般。 火紅的嫁衣襯著肌膚如雪棚饵。 梳的紋絲不亂的頭發(fā)上煤裙,一...
    開封第一講書人閱讀 52,584評(píng)論 1 312
  • 那天,我揣著相機(jī)與錄音噪漾,去河邊找鬼硼砰。 笑死,一個(gè)胖子當(dāng)著我的面吹牛怪与,可吹牛的內(nèi)容都是我干的夺刑。 我是一名探鬼主播,決...
    沈念sama閱讀 41,085評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼分别,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了存淫?” 一聲冷哼從身側(cè)響起耘斩,我...
    開封第一講書人閱讀 40,023評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎桅咆,沒想到半個(gè)月后括授,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,555評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡岩饼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,626評(píng)論 3 342
  • 正文 我和宋清朗相戀三年荚虚,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片籍茧。...
    茶點(diǎn)故事閱讀 40,769評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡版述,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出寞冯,到底是詐尸還是另有隱情渴析,我是刑警寧澤晚伙,帶...
    沈念sama閱讀 36,439評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站俭茧,受9級(jí)特大地震影響咆疗,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜母债,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,115評(píng)論 3 335
  • 文/蒙蒙 一午磁、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧毡们,春花似錦漓踢、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,601評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至青责,卻和暖如春挺据,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背脖隶。 一陣腳步聲響...
    開封第一講書人閱讀 33,702評(píng)論 1 274
  • 我被黑心中介騙來泰國打工扁耐, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人产阱。 一個(gè)月前我還...
    沈念sama閱讀 49,191評(píng)論 3 378
  • 正文 我出身青樓婉称,卻偏偏與公主長得像,于是被迫代替她去往敵國和親构蹬。 傳聞我的和親對(duì)象是個(gè)殘疾皇子王暗,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,781評(píng)論 2 361

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

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,318評(píng)論 25 707
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件庄敛、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,124評(píng)論 4 61
  • 雨一直下藻烤,從昨晚至今天绷雏,早晨上班路上,心里一陣驚喜怖亭,雨傘終于派上用場了涎显,要是在南方,雨傘是出門的必備品兴猩,因?yàn)槎鄶?shù)時(shí)...
    女公子99閱讀 253評(píng)論 1 1
  • 指尖微涼 下雨了 天空灰霾 抬頭時(shí)總有一絲傷感 而我卻喜歡在這種氣氛中提筆讓思緒亂飛 如果是在以前 濤子現(xiàn)在一定在...
    王十一_1a26閱讀 238評(píng)論 0 0