欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

iOS渐变导航栏封装

程序员文章站 2022-05-04 14:22:11
由于最近开发的几个项目都有渐变导航栏,每次写的时候都要copy一堆关于导航渐变相关的代码,显得类很冗余,所以花了点时间封装了一个渐变类,直接继承就可以满足大部分需求啦,这里简单写一下心路历程: 渐变的核心几个部分: 1.状态栏的变色: 添加一个状态栏属性BooL变量 @property(nonato ......

由于最近开发的几个项目都有渐变导航栏,每次写的时候都要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添加一个分类添加如下

iOS渐变导航栏封装

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

 

2.导航栏的渐变

先做一下基础的设置:

1.禁止系统对继承scrollview的控件的自动偏移iOS渐变导航栏封装

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

iOS渐变导航栏封装

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

    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 方法里面就是做上面三件事啦

iOS渐变导航栏封装

 

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

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