上一章講解了自定義tabBar,本章講解怎樣簡單的自定義UINavigationController以及UIScrollView滑動頁面的聯(lián)動。
一、設(shè)置導(dǎo)航欄背景顏色
確保當(dāng)前控制器已擁有導(dǎo)航欄
self.navigationController.navigationBar.barTintColor = JHRGB(76, 201, 245);
二、設(shè)置左右item
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc]initWithImage:[UIImage imageNamed:@"global_search"] style:UIBarButtonItemStyleDone target:nil action:nil];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc]initWithImage:[UIImage imageNamed:@"title_button_more"] style:UIBarButtonItemStyleDone target:nil action:nil];
此時效果圖

nav0.png
可以看到item的圖片被渲染了,可以使用tintColor設(shè)置控件顏色
self.navigationController.navigationBar.tintColor = [UIColor whiteColor];
此時效果圖

nav1.png
三、創(chuàng)建ScrollView
//這里為了方便我是直接用的storyboard
@property (weak, nonatomic) IBOutlet UIScrollView *contentScrollView;
- 引入子控制器
NSArray * vcName = @[@"JHLeftVC",@"JHMiddleVC",@"JHRightVC"];
for (NSInteger i=0; i<vcName.count; i++) {
NSString *vcNameStr = vcName[I];
UIViewController * vc = [[NSClassFromString(vcNameStr) alloc]init];
vc.title = self.dataList[I];
[self addChildViewController:vc];
}
- 設(shè)置contentScrollView
//設(shè)置scrollView的contentSize
self.contentScrollView.contentSize = CGSizeMake(SCREEN_WIDTH * self.dataList.count, 0);
self.contentScrollView.delegate = self;
self.contentScrollView.pagingEnabled = YES;
//默認(rèn)先展示第二個界面
self.contentScrollView.contentOffset = CGPointMake(SCREEN_WIDTH, 0);
//進(jìn)入主控制器時加載頁面
[self scrollViewDidEndScrollingAnimation:self.contentScrollView];
- 設(shè)置代理方法
#pragma mark --- UIScrollViewDelegate
//減速結(jié)束時調(diào)用。加載子控制器view
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
CGFloat width = SCREEN_WIDTH;
CGFloat height = SCREEN_HEIGHT;
CGFloat offset = scrollView.contentOffset.x;
//獲取第幾個 的索引值
NSInteger idx = offset / width;
//根據(jù)索引值,返回vc的引用
UIViewController * vc = self.childViewControllers[idx];
//判讀當(dāng)前vc是否執(zhí)行過viewDidLoad
if ([vc isViewLoaded]) return;
//設(shè)置子控制器view的大小
vc.view.frame = CGRectMake(offset, 0, width, height);
//將子控制器view加入到scrollView上
[scrollView addSubview:vc.view];
}
此時的效果圖

scrollView0.gif
四、自定義topView[navigationItem.titleView]
創(chuàng)建topView替換navigationItem.titleView
定義方法
-(instancetype)initWithFrame:(CGRect)frame titleNames:(NSArray *)titles;定義屬性
/** topView的按鈕 */
@property (nonatomic, strong) NSMutableArray * buttons;
/** topView按鈕下的線條 */
@property (nonatomic, strong)UIView *lineView;
- 懶加載buttons
-(NSArray *)buttons{
if (!_buttons) {
_buttons = [NSMutableArray array];
}
return _buttons;
}
- 實現(xiàn)方法
-(instancetype)initWithFrame:(CGRect)frame titleNames:(NSArray *)titles{
self = [super initWithFrame:frame];
if (self) {
CGFloat btnW = self.frame.size.width/titles.count;
CGFloat btnH = self.frame.size.height;
for (NSInteger i=0; i<titles.count; i++) {
UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
NSString * vcTitle = titles[I];
[button setTitle:vcTitle forState:UIControlStateNormal];
[button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
button.titleLabel.font = [UIFont systemFontOfSize:18];
button.frame = CGRectMake(i*btnW, 0, btnW, btnH);
[button addTarget:self action:@selector(clickTitle:) forControlEvents:UIControlEventTouchUpInside];
button.tag = i;//設(shè)置block的回傳
[self addSubview:button];
[self.buttons addObject:button];
}
}
return self;
}
//topView的button點擊事件
-(void)clickTitle:(UIButton *)button{
}
- 在之前的VC中導(dǎo)入頭文件
[這個類里我使用了YYKit]
#import "JHTopView.h"
- 創(chuàng)建topView屬性
@property (nonatomic, strong) JHTopView * topView;
-(JHTopView *)topView{
if (!_topView) {
_topView = [[JHTopView alloc]initWithFrame:CGRectMake(0, 0, 200, 50) titleNames:self.dataList];
};
}
return _topView;
}
- 替換navigationItem.titleView
self.navigationItem.titleView = self.topView;
此時效果圖

topView1.png
五、設(shè)置lineView
if (i == 1) {
CGFloat h = 2;
CGFloat y = 40;
[button.titleLabel sizeToFit];
self.lineView = [[UIView alloc]init];
self.lineView.backgroundColor = [UIColor whiteColor];
self.lineView.height = h;
self.lineView.width = button.titleLabel.width;
self.lineView.top = y;
self.lineView.centerX = button.centerX;
[self addSubview:self.lineView];
}
六、lineView與button的聯(lián)動
- 設(shè)置block與滑動方法
typedef void(^TopBlock)(NSInteger tag);
@property ( nonatomic, copy) TopBlock block;
-(void)scrolling:(NSInteger)idx;
- button的事件
//topView的button點擊事件
-(void)clickTitle:(UIButton *)button{
self.lineView.centerX = button.centerX;
}
七、topView與scrollView的聯(lián)動
- 修改button點擊事件
//topView的button點擊事件
-(void)clickTitle:(UIButton *)button{
self.block(button.tag);
//點擊按鈕,使ScrollView滑動到相應(yīng)位置(展示相應(yīng)的子視圖控制器)
[self scrolling:button.tag];
}
//VC滾動時調(diào)用
-(void)scrolling:(NSInteger)idx{
UIButton * button = self.buttons[idx];
//點擊按鈕,使line滑動到相應(yīng)位置
[UIView animateWithDuration:0.2 animations:^{
self.lineView.centerX = button.centerX;
}];
}
- 修改topView的懶加載
@weakify(self);
_topView.block = ^(NSInteger tag) {
@strongify(self);
CGPoint point = CGPointMake(tag * SCREEN_WIDTH, self.contentScrollView.contentOffset.y);
[self.contentScrollView setContentOffset:point animated:YES];
};
- 傳遞聯(lián)動索引值給topView
[self.topView scrolling:idx];
最終效果圖

finish0.gif
補(bǔ)充
UINavigationController的常用屬性及方法---->傳送門