iOS 自定义UINavigationController+UIScrollView联动

上一章讲解了自定义tabBar,本章讲解怎样简单的自定义UINavigationController以及UIScrollView滑动页面的联动。

一、设置导航栏背景颜色

确保当前控制器已拥有导航栏

self.navigationController.navigationBar.barTintColor = JHRGB(76, 201, 245);   

二、设置左右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设置控件颜色
self.navigationController.navigationBar.tintColor = [UIColor whiteColor];   
此时效果图
nav1.png

三、创建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];
    }   
  • 设置contentScrollView
 //设置scrollView的contentSize
    self.contentScrollView.contentSize = CGSizeMake(SCREEN_WIDTH * self.dataList.count, 0);
    
    self.contentScrollView.delegate = self;
    self.contentScrollView.pagingEnabled = YES;
    //默认先展示第二个界面
    self.contentScrollView.contentOffset = CGPointMake(SCREEN_WIDTH, 0);
    
    //进入主控制器时加载页面
    [self scrollViewDidEndScrollingAnimation:self.contentScrollView];   
  • 设置代理方法
#pragma mark --- UIScrollViewDelegate
//减速结束时调用。加载子控制器view
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
    CGFloat width = SCREEN_WIDTH;
    CGFloat height = SCREEN_HEIGHT;
    CGFloat offset = scrollView.contentOffset.x;
    
    //获取第几个  的索引值
    NSInteger idx = offset / width;
    
    //根据索引值,返回vc的引用
    UIViewController * vc = self.childViewControllers[idx];
    
    //判读当前vc是否执行过viewDidLoad
    if ([vc isViewLoaded]) return;
    
    //设置子控制器view的大小
    vc.view.frame = CGRectMake(offset, 0, width, height);
    
    //将子控制器view加入到scrollView上
    [scrollView addSubview:vc.view];
}   
此时的效果图
scrollView0.gif

四、自定义topView[navigationItem.titleView]

  • 创建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;
}   
  • 实现方法
-(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;//设置block的回传
            
            [self addSubview:button];
            
            [self.buttons addObject:button];
            
        }
    }
    return self;
}   

//topView的button点击事件
-(void)clickTitle:(UIButton *)button{
    
}   
   
  • 在之前的VC中导入头文件[这个类里我使用了YYKit]
#import "JHTopView.h"   
  • 创建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

五、设置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的联动

  • 设置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的联动

  • 修改button点击事件
//topView的button点击事件
-(void)clickTitle:(UIButton *)button{
    
    self.block(button.tag);

    //点击按钮,使ScrollView滑动到相应位置(展示相应的子视图控制器)
    [self scrolling:button.tag];
}

//VC滚动时调用
-(void)scrolling:(NSInteger)idx{
    
    UIButton * button = self.buttons[idx];

    //点击按钮,使line滑动到相应位置
    [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];
            
        };   
  • 传递联动索引值给topView
[self.topView scrolling:idx];   
最终效果图
finish0.gif

补充

UINavigationController的常用属性及方法---->传送门

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,612评论 5 471
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,345评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,625评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,022评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,974评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,227评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,688评论 3 392
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,358评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,490评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,402评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,446评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,126评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,721评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,802评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,013评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,504评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,080评论 2 341

推荐阅读更多精彩内容

  • “北灵之原修行?” 牧尘听得此话,倒是微微怔了怔,北灵之原是北灵境内相当闻名的一处险地,其中地域辽阔,更是遍布着各...
    混沌天书阅读 170评论 0 0
  • 很多时侯,人就是一个演员,天生自带剧本,但是很多人却没有信念感,往往那些不阿谀奉承、不把眼光像个饿狼般向外索取的 ...
    一岁一礼一欢喜阅读 911评论 0 0
  • 看了同学们的日记,收获二字“认真”,每个人都在认真对待自己的每一天。Legcay 的战斗力不容低估,我们是一群在不...
    天之心语阅读 199评论 0 1
  • 先看照片吧,今天回学校,发现了近在身边的牛人: 滴滴打车CTO,贝贝网创始人,虹膜算法领导者,pptv创始人,悦然...
    京珂大师姐阅读 230评论 3 4
  • 001.想到就去做,今日复明日,明日何其多!做了,才能知道会有下一个可能。每个人都有拖延症,那是因为这件事对你来说...
    June88阅读 191评论 0 0