iOS開發(fā)之分段滑動視圖

最近公司需要做類似分段選擇的功能,自己研究了下余寥,基本完成了業(yè)務(wù)需求肋杖,抽時間把這個控制器封裝了一遍:

1.下面先演示下實際效果:

Simulator Screen Shot 2016年6月2日 下午6.07.17.png
Simulator Screen Shot 2016年6月2日 下午6.07.20.png

2.使用的話比較簡單,在封裝控制器中提供了一個類方法

// 通過傳入標(biāo)題數(shù)組和控制器數(shù)組來創(chuàng)建當(dāng)前的根控制器
- (id)initWithTitleArray:(NSArray *)titleArray controllersArray:(NSArray *)controllersArray;

// 下面的代碼為演示方法
- (IBAction)jumpToSelectView:(id)sender {
   
   NSArray *titleArray = @[@"第一頁",@"第二頁222",@"第三頁3",@"第四頁44444"];
   
   NSMutableArray *controllersArray = [NSMutableArray array];
   for (int i = 0; i < 4; i++) {
       UIViewController *vc1 = [[UIViewController alloc] init];
       vc1.view.backgroundColor = RandomColor;
       [controllersArray addObject:vc1];
   }
   
   CWSegmentRootController *rootVc = [[CWSegmentRootController alloc] initWithTitleArray:titleArray controllersArray:controllersArray];
   UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:rootVc];
   
   [self presentViewController:nav animated:YES completion:nil];

}

3.下面說下具體實現(xiàn)過程

. 首先整個視圖分為上面的標(biāo)題視圖以及下面的內(nèi)容視圖吊说,標(biāo)題視圖主要分為標(biāo)題Button和下面的指示器,具體的創(chuàng)建是根據(jù)標(biāo)題數(shù)組的數(shù)量確定的:

/**
* 設(shè)置頂部的標(biāo)簽欄
*/
- (void)setupTitlesView
{
   // 標(biāo)簽欄整體
   UIView *titlesView = [[UIView alloc] init];
   titlesView.backgroundColor = [[UIColor whiteColor] colorWithAlphaComponent:1.0];
   titlesView.frame = CGRectMake(0, 64, self.view.frame.size.width, 35);
   [self.view addSubview:titlesView];
   self.titlesView = titlesView;
   
   // 底部的紅色指示器
   UIView *indicatorView = [[UIView alloc] init];
   indicatorView.backgroundColor = [UIColor redColor];
   indicatorView.tag = -1;
 
   CGFloat indicatorViewW = self.view.frame.size.width/(self.titlesArray.count);
   CGFloat indicatorViewH = 2;
   CGFloat indicatorViewY = titlesView.frame.size.height - indicatorViewH;
   
   indicatorView.frame = CGRectMake(0, indicatorViewY, indicatorViewW, indicatorViewH);
   
   self.indicatorView = indicatorView;
   
   // 內(nèi)部的子標(biāo)簽
   CGFloat width = titlesView.frame.size.width / self.titlesArray.count;
   CGFloat height = titlesView.frame.size.height;
   for (NSInteger i = 0; i<self.titlesArray.count; i++) {
       UIButton *button = [[UIButton alloc] init];
       button.tag = i;
       button.frame = CGRectMake(i*width, 0, width, height);
       [button setTitle:self.titlesArray[i] forState:UIControlStateNormal];
       //        [button layoutIfNeeded]; // 強(qiáng)制布局(強(qiáng)制更新子控件的frame)
       [button setTitleColor:[UIColor grayColor] forState:UIControlStateNormal];
       [button setTitleColor:[UIColor redColor] forState:UIControlStateDisabled];
       button.titleLabel.font = [UIFont systemFontOfSize:14];
       [button addTarget:self action:@selector(titleClick:) forControlEvents:UIControlEventTouchUpInside];
       [titlesView addSubview:button];
       
       // 默認(rèn)點擊了第一個按鈕
       if (i == 0) {
           button.enabled = NO;
           self.selectedButton = button;
           
           // 讓按鈕內(nèi)部的label根據(jù)文字內(nèi)容來計算尺寸
           [button.titleLabel sizeToFit];
           
           CGRect newFrame = indicatorView.frame;
           newFrame.size.width = button.titleLabel.frame.size.width;
           self.indicatorView.frame = newFrame;
           CGPoint newCenter = self.indicatorView.center;
           newCenter.x = button.center.x;
           self.indicatorView.center = newCenter;
       }
   }
   
   [titlesView addSubview:indicatorView];

}

. 然后是添加內(nèi)容容器ScrollView,這里注意設(shè)置ContentSize(根據(jù)控制器數(shù)組的數(shù)量確定的)

/**
* 底部的scrollView
*/
- (void)setupContentView
{
   // 不要自動調(diào)整inset
   self.automaticallyAdjustsScrollViewInsets = NO;
   
   UIScrollView *contentView = [[UIScrollView alloc] init];
   contentView.backgroundColor = [UIColor lightGrayColor];
   //    contentView.frame = self.view.bounds;
   contentView.frame = CGRectMake(0, CGRectGetMaxY(self.titlesView.frame), self.view.frame.size.width, self.view.frame.size.height-CGRectGetMaxY(self.titlesView.frame));
   
   contentView.delegate = self;
   contentView.pagingEnabled = YES;
   [self.view insertSubview:contentView atIndex:0];
   contentView.contentSize = CGSizeMake(contentView.frame.size.width * self.childViewControllers.count, 0);
   self.contentView = contentView;
   
   // 添加第一個控制器的view
   [self scrollViewDidEndScrollingAnimation:contentView];
}

. 最后需要將傳入的多個控制器傳入根控制器中:

/**
* 初始化子控制器
*/
- (void)setupChildVces
{
   for (UIViewController *vc in self.controllersArray) {
       [self addChildViewController:vc];
   }
}

4.接下來需要監(jiān)聽標(biāo)題按鈕的點擊以及內(nèi)容視圖的滾動

// 標(biāo)題按鈕點擊時需要滾動視圖以及讓指示器移動
- (void)titleClick:(UIButton *)button
{
   // 修改按鈕狀態(tài)
   self.selectedButton.enabled = YES;
   button.enabled = NO;
   self.selectedButton = button;
   
   // 動畫
   [UIView animateWithDuration:0.25 animations:^{
       CGRect newFrame = self.indicatorView.frame;
       newFrame.size.width = button.titleLabel.frame.size.width;
       self.indicatorView.frame = newFrame;
       CGPoint newCenter = self.indicatorView.center;
       newCenter.x = button.center.x;
       self.indicatorView.center = newCenter;
   }];
   
   // 滾動
   CGPoint offset = self.contentView.contentOffset;
   offset.x = button.tag * self.contentView.frame.size.width;
   [self.contentView setContentOffset:offset animated:YES];
}

5.最后需要監(jiān)聽ScrollView的代理方法

#pragma mark - <UIScrollViewDelegate>
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
{
   // 當(dāng)前的索引
   NSInteger index = scrollView.contentOffset.x / scrollView.frame.size.width;
   
   // 取出子控制器
   UIViewController *vc = self.childViewControllers[index];
   
   vc.view.frame = CGRectMake(scrollView.contentOffset.x, 0, scrollView.frame.size.width, scrollView.frame.size.height);
   
   [scrollView addSubview:vc.view];
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
   [self scrollViewDidEndScrollingAnimation:scrollView];
   
   // 點擊按鈕
   NSInteger index = scrollView.contentOffset.x / scrollView.frame.size.width;
   [self titleClick:self.titlesView.subviews[index]];
}

6.實現(xiàn)過程差不多就是這么多了,比較簡單优炬,后期我會完善一下颁井,下面附上代碼地址:

Github地址

如果對大家有幫助的話希望給我喜歡或關(guān)注,非常感謝蠢护!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末雅宾,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子糊余,更是在濱河造成了極大的恐慌秀又,老刑警劉巖单寂,帶你破解...
    沈念sama閱讀 212,029評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件贬芥,死亡現(xiàn)場離奇詭異吐辙,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)蘸劈,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,395評論 3 385
  • 文/潘曉璐 我一進(jìn)店門昏苏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人威沫,你說我怎么就攤上這事贤惯。” “怎么了棒掠?”我有些...
    開封第一講書人閱讀 157,570評論 0 348
  • 文/不壞的土叔 我叫張陵孵构,是天一觀的道長。 經(jīng)常有香客問我烟很,道長颈墅,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,535評論 1 284
  • 正文 為了忘掉前任雾袱,我火速辦了婚禮恤筛,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘芹橡。我一直安慰自己毒坛,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,650評論 6 386
  • 文/花漫 我一把揭開白布林说。 她就那樣靜靜地躺著煎殷,像睡著了一般。 火紅的嫁衣襯著肌膚如雪腿箩。 梳的紋絲不亂的頭發(fā)上蝌数,一...
    開封第一講書人閱讀 49,850評論 1 290
  • 那天,我揣著相機(jī)與錄音度秘,去河邊找鬼顶伞。 笑死,一個胖子當(dāng)著我的面吹牛剑梳,可吹牛的內(nèi)容都是我干的唆貌。 我是一名探鬼主播,決...
    沈念sama閱讀 39,006評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼垢乙,長吁一口氣:“原來是場噩夢啊……” “哼锨咙!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起追逮,我...
    開封第一講書人閱讀 37,747評論 0 268
  • 序言:老撾萬榮一對情侶失蹤酪刀,失蹤者是張志新(化名)和其女友劉穎粹舵,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體骂倘,經(jīng)...
    沈念sama閱讀 44,207評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡眼滤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,536評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了历涝。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片诅需。...
    茶點故事閱讀 38,683評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖荧库,靈堂內(nèi)的尸體忽然破棺而出堰塌,到底是詐尸還是另有隱情,我是刑警寧澤分衫,帶...
    沈念sama閱讀 34,342評論 4 330
  • 正文 年R本政府宣布场刑,位于F島的核電站,受9級特大地震影響蚪战,放射性物質(zhì)發(fā)生泄漏牵现。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,964評論 3 315
  • 文/蒙蒙 一屎勘、第九天 我趴在偏房一處隱蔽的房頂上張望施籍。 院中可真熱鬧,春花似錦概漱、人聲如沸丑慎。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,772評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽竿裂。三九已至,卻和暖如春照弥,著一層夾襖步出監(jiān)牢的瞬間腻异,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,004評論 1 266
  • 我被黑心中介騙來泰國打工这揣, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留悔常,地道東北人。 一個月前我還...
    沈念sama閱讀 46,401評論 2 360
  • 正文 我出身青樓给赞,卻偏偏與公主長得像机打,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子片迅,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,566評論 2 349

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