美文网首页
iOS- 一种自定义NavigationBar的方式

iOS- 一种自定义NavigationBar的方式

作者: codemovie | 来源:发表于2019-04-09 12:18 被阅读0次

    NavigationBar这个最基本的控件想必大家都接触的不少,更是有各种各样的自定义的方式。我这边也分享一种根据项目需求而构想的自定义NavigationBar,可能并不是很通用,权当参考。

    先看下项目界面简图:

    界面.png

    Bar左边三个控件,返回按钮,logo图片,当前页面的title相对来说是固定的,除了最基础的几个Tab页面不需要返回按钮,每个页面都有这三个控件。
    Bar右边是不同的功能按钮,数量0-3个不等。

    接下来具体实现。
    采用UIView来模拟NavigationBar,所以在NavigationController中先隐藏navigaitonBar

    self.navigationBar.hidden = YES;
    

    然后将自定义的navigationBar(下称CustomNaviBar)添加到NavigationController中。

    CustomNaviBar初始创建时只添加logo imageView和title Label这两个控件。

    CustomNaviBar提供如下几个方法:

    /**
    更新当前页面title
    页面初始化时调用 (建议viewDidAppear)
    */
    - (void)updateNaviBarTitle:(NSSring *)title;
    

    更新title方法实现即给Label赋值,设置布局,这里提一个小点,为了某些页面title是灵活配置的布局正常,传入的title去除收尾空格。

    self.titleLabel.text = [title stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
    
    
    /**
     添加返回按钮
     push到下一个页面时,在NavigationController中调用
    */
    - (void)remakeSubViewsForBackBtn;
    

    这个方法顾名思义,添加返回按钮。方法的实现也仅仅是添加按钮,调整控件布局。
    在调用时,可以在NavigationController中调用

    - (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated {
        [super pushViewController:viewController animated:YES];
        [self.baseNaviBar remakeSubViewsForBackBtn];
    }
    
    /**
     清除返回按钮
     */
    - (void)clearForBackBtn;
    

    有创建也就有移除,返回到基础Tab页面时需要调用此方法来清除返回按钮。

    - (void)viewDidAppear:(BOOL)animated {
        [super viewDidAppear:animated];
        [self.naviController.baseNaviBar updateNaviBarTitle:@"主页"];
        [self.naviController.baseNaviBar clearForBackBtn];
    }
    
    /**
    单独添加一个右边的按钮
    */
    - (void)addSingleRightBtnWithTitle:(NSString *)title ButtonImage:(NSString *)imageName Target:(id)target Action:(SEL)action;
    
    

    刚刚提到右侧的功能键数量0-3个不等,这里先给到一个创建一个按钮的方法,方法参数中传入target以及点击事件。
    此方法的实现中,除了给btn布局和添加点击事件以外,需要提一小点是

    [self.rightButton setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
    [self.titleLabel setContentCompressionResistancePriority:UILayoutPriorityDefaultLow forAxis:UILayoutConstraintAxisHorizontal];
    

    设置约束的优先级,以免某些页面title文字过长导致和右侧按钮约束冲突。

    /**
     添加自定义按钮
     由右向左添加!
     填入buttonTitles参数也按照从右向左的顺序。
     buttonConfiguration:
     @{
     @"title":@"标题",
     @"image":@"图片名",
     @"action":action,//button点击方法,传入NSInvocation类型参数
     }
     */
    - (void)addButtonWithButtonConfiguration:(NSDictionary *)buttonConfiguration,...NS_REQUIRES_NIL_TERMINATION;
    
    

    右侧有多个按钮的页面就由此方法来实现,比较关键的两点是:
    1> NS_REQUIRES_NIL_TERMINATION 宏
    在创建字典,数组时肯定没少用过这类方法

    NSArray arrayWithObjects:<#(nonnull ObjectType), ...#>, nil
    

    自己来实现这个写法时,核心代码如下:

    - (void)addButtonWithButtonConfiguration:(NSDictionary *)buttonConfiguration, ... {
        va_list argList;
        if (buttonConfiguration) {
            va_start(argList, buttonConfiguration);
            NSDictionary *configuraDict;
            //这样每次循环argList所代表的指针偏移量就不断下移直到取出nil
            while ((configuraDict = va_arg(argList, id))) {
                 //这里设置btn布局,添加点击事件
            }
        }
        va_end(argList);
    }
    

    2>传入NSInvocation类型参数
    直接上代码,创建一个NSInvocation对象

    + (NSInvocation *)creatInvocationWithTarget:(id)target Action:(SEL)action {
        NSMethodSignature *signature = [target methodSignatureForSelector:action];
        NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
        invocation.target = target;
        invocation.selector = action;
        return invocation;
    }
    

    NSInvocation有其他更有趣好用的使用场景,在此处大材小用了,仅仅是因为需要作为参数包装到字典中,其他用法这里先不赘述了。

    添加btn方法调用示例如下:

    - (void)viewDidAppear:(BOOL)animated {
        [super viewDidAppear:animated];
        [self.naviController.baseNaviBar updateNaviBarTitle:@"主页"];
        [self.naviController.baseNaviBar clearForBackBtn];
    
        [self.naviController.baseNaviBar addButtonWithButtonConfiguration:
         @{@"title":@"btn1",@"image":@"image1",@"action":[CreatActionTool creatInvocationWithTarget:self Action:@selector(click1)]},
         @{@"title":@"btn2",@"image":@"image2",@"action":[CreatActionTool creatInvocationWithTarget:self Action:@selector(click2)]},nil];
    }
    

    在添加btn点击事件时如下:

     NSInvocation *action = [configuraDict objectForKey:@"action"];//configuraDict为在上述方法中循环取出的btn配置数据
     UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
     [button addTarget:action.target action:action.selector forControlEvents:UIControlEventTouchUpInside];
    
    

    提供主要功能的几个方法如上所述,还可以随意添加一些自定义功能。
    因为代码中为了项目需求,做了好多适配,也不是通用的方法,后面整理好再上传~

    相关文章

      网友评论

          本文标题:iOS- 一种自定义NavigationBar的方式

          本文链接:https://www.haomeiwen.com/subject/svnviqtx.html