zoukankan      html  css  js  c++  java
  • iOS渐变导航栏封装

    由于最近开发的几个项目都有渐变导航栏,每次写的时候都要copy一堆关于导航渐变相关的代码,显得类很冗余,所以花了点时间封装了一个渐变类,直接继承就可以满足大部分需求啦,这里简单写一下心路历程:

    渐变的核心几个部分:

    1.状态栏的变色:

    添加一个状态栏属性BooL变量

    @property(nonatomic,assign)BOOL lightStatusBar;//状态栏的颜色控制

    我们可以在ViewController里面重写系统的这个方法来动态设置状态栏颜色(白色/黑色):
    -(UIStatusBarStyle)preferredStatusBarStyle{
        return self.lightStatusBar ? UIStatusBarStyleLightContent : UIStatusBarStyleDefault;
    }
    如果需要主动的触发上面的方法改变状态栏颜色,我们可以直接调用这个方法 [self setNeedsStatusBarAppearanceUpdate];在ViewController写完上面两步,滑动导航栏会发现好像没什么卵用,状态栏颜色没变啊!

    因为我们需要在UINavigationController里面重写下面这个方法-(UIViewController *)childViewControllerForStatusBarStyle;为什么要重写这个?这个方法默认返回值是nil,也就是当我们调用setNeedsStatusBarAppearanceUpdate的时候,系统会调用container(容器控制器)的preferredStatusBarStyle这个方法(app.window.rootViewController的preferred的方法,一般我们用UINavigationController或者UITabBarController来做container),也就是根本不会调用子控制器(我们所看到的UIViewcontroller)的preferredStatusBarStyle方法。这个时候- (UIViewController *)childViewControllerForStatusBarStyle:就派上用场了

    给UINavigationController添加一个分类添加如下

    重写这个方法,系统会调用container(容器控制器)就会返回当前的UIViewController,从而UIViewController里面重写的方法就会调用,状态栏的颜色就会相应改变。以上就是状态栏的变色出处理

    2.导航栏的渐变

    先做一下基础的设置:

    1.禁止系统对继承Scrollview的控件的自动偏移

    2.隐藏导航栏底部的线条,不处理的话导航栏透明时会明显看到一条黑线,辣眼睛。写个递归找到线条

    调用上面方法找到线条图片,隐藏即可。

        UIImageView *iamgeV = [self findBackLineImageV:self.navigationController.navigationBar];
        iamgeV.hidden = YES;

    当我们滑动的时候会触发代理方法(必须要是继承Scrollview的控件设置代理才会触发):

    -(void)scrollViewDidScroll:(UIScrollView *)scrollView{
    }

    在上面的方法我们主要做以下几件事情(把上面方法内容拆分说明一下):

    1.滑动偏移量获取,通过滑动偏移量计算导航栏的透明度。

    -(void)scrollViewDidScroll:(UIScrollView *)scrollView{
        offset = scrollView.contentOffset.y;
        UIColor *color = [UIColor colorWithWhite:1.0 alpha:offset/self.offsetChange];
        [self.navigationController.navigationBar setBackgroundImage:[self imageWithColor:color] forBarMetrics:UIBarMetricsDefault];
    }

     //绘制一张图片
    - (UIImage *)imageWithColor:(UIColor *)color {
        CGSize size = CGSizeMake(1, 1);
        if (!color || size.width <= 0 || size.height <= 0) return nil;
        CGRect rect = CGRectMake(0.0f, 0.0f, size.width, size.height);
        UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0);
        CGContextRef context = UIGraphicsGetCurrentContext();
        CGContextSetFillColorWithColor(context, color.CGColor);
        CGContextFillRect(context, rect);
        UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        return image;
    }

    2.滑动偏移量到设置的偏移量临界值时的处理(切换back图片,标题文字颜色,状态栏的bool值等)。

    -(void)scrollViewDidScroll:(UIScrollView *)scrollView{

        //导航栏渐变处理
        if (offset >= _offsetChange) {
            [self setBackNavNomal];
        }else{
            [self setBackNavDiaphanous];
        }
    }

    //不透明导航栏
    -(void)setBackNavNomal
    {
        self.navigationController.navigationBar.titleTextAttributes=@{NSForegroundColorAttributeName: self.notLucencyTitleColor,NSFontAttributeName:[UIFont systemFontOfSize:18]};
        [self setNavigationLeftItemWithImageName:@"more_dark"];
        [self.rightBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
        self.lightStatusBar = NO;
    }

    //透明导航栏
    -(void)setBackNavDiaphanous
    {
        self.navigationController.navigationBar.titleTextAttributes= @{NSForegroundColorAttributeName: self.lucencyTitleColor,NSFontAttributeName:[UIFont systemFontOfSize:18]};
        [self setNavigationLeftItemWithImageName:@"navigationBack"];
         [self.rightBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
        self.lightStatusBar = YES;
    }

    3.当tableview有组头并且组头要悬浮在导航栏下面,需要做的处理。

     self.contentHeight为tableview的占屏大小,如果contentSize不用滑动就能显示完整,contentInset就不要修改,不然向上滑会有点bug。

     self.offsetChange参数:没组头一般默认64就行,有组头则为组头到顶部的距离

    -(void)scrollViewDidScroll:(UIScrollView *)scrollView{

     if (self.tableView.contentSize.height >= self.contentHeight) {
            //导航栏渐变处理
            if (offset >= self.offsetChange) {
                self.tableView.contentInset = UIEdgeInsetsMake(KStatusBarAndNavigationBarHeight, 0, 0, 0);
            }else{
                self.tableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0);
            }

         }

    }

    整体-(void)scrollViewDidScroll:(UIScrollView *)scrollView 方法里面就是做上面三件事啦

     做完这些就可以实现渐变了,项目中用的比较多的话直接继承设置一下参数就可以了。

     demon地址:https://github.com/yizhixiafancai/ShadeViewController

  • 相关阅读:
    PHP随机浮点数
    mysql中的包含语句INSTR的使用
    jquery全面判断是否IE6浏览器
    jquery中获取radio选中值的正确写法
    淘宝IP地址库API地址
    php判断是否是ajax提交 方法
    ejs模板引擎
    webpack配置非CMD规范的模块
    JavaScript中的浅拷贝和深拷贝
    css display:flex 属性
  • 原文地址:https://www.cnblogs.com/xiafancai/p/10321141.html
Copyright © 2011-2022 走看看