iOS之導(dǎo)航欄的漸變隱藏及顯示

在項(xiàng)目中往往有的時(shí)候需要導(dǎo)航欄的狀態(tài)是變化的,有的時(shí)候需要隱藏,為的是顯示更多的頁面,有的時(shí)候需要顯示出來,給用戶以提示,所以就需要隱藏和顯示導(dǎo)航欄。正如下面的示意圖所示:


示意圖

分析

本個(gè)項(xiàng)目中,展示的是一個(gè)導(dǎo)航控制器,其中導(dǎo)航控制器中有個(gè)UIViewController或者是UITableviewController為根控制器的這么一個(gè)結(jié)構(gòu)。

實(shí)現(xiàn)

因此在storyboard中我們將之前控制器刪除,然后拖一個(gè)導(dǎo)航控制器出來,然后試著先綁定一個(gè)UITableviewController為根控制器。

導(dǎo)航欄的設(shè)置

為了讓我們的header view所展示的位置是在左上角的圓點(diǎn)位置,我們需要把自動(dòng)偏移設(shè)置關(guān)掉。

    self.automaticallyAdjustsScrollViewInsets = NO;

下面就需要隱藏導(dǎo)航欄操作了,我們都知道導(dǎo)航欄有一個(gè)隱藏的屬性,下面試試

    self.navigationController.navigationBar.hidden = YES;

這種方法雖然能夠讓導(dǎo)航欄消失隱藏掉,但是如果我們要進(jìn)行滾動(dòng)tableview的時(shí)候,就不能讓導(dǎo)航欄漸變的顯示出來,所以這種方法不能滿足要求。
這種方法行不通那么用透明度的方案來試試:

    self.navigationController.navigationBar.alpha = 0;

截圖如下:


導(dǎo)航欄沒有消失掉

因此上面的方案不能實(shí)現(xiàn)功能。
可以使用設(shè)置導(dǎo)航欄背景圖片進(jìn)行設(shè)置,這樣就可以設(shè)置導(dǎo)航欄的背景有個(gè)透明度的變化。

    [self.navigationController.navigationBar setBackgroundImage:nil forBarMetrics:UIBarMetricsDefault];

當(dāng)傳入的圖片為nil的時(shí)候,會(huì)自動(dòng)的創(chuàng)建一個(gè)半透明的圖片作為導(dǎo)航欄的背景。所以這種方案是可行的,但是導(dǎo)航欄下面的那一根線我們是希望不顯示的:

    [self.navigationController.navigationBar setShadowImage:[[UIImage alloc] init]];

這樣一來,導(dǎo)航欄的那根線就取消掉了。
以上導(dǎo)航欄的基本實(shí)現(xiàn)方案已經(jīng)確定了,但是下面的列表的顯示還有些疑問,到底是用的tableview顯示,利用tableview的headerView;還是用UIViewController進(jìn)行展示頭部的控件,下面的部分就用tableview進(jìn)行展示。

UITableviewController 方案

我們先試著作出示意圖的效果,一個(gè)tableview上放置一個(gè)headerView。

    UIView *header = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, 200)];
    header.backgroundColor = [UIColor redColor];
    self.tableView.tableHeaderView = header;

運(yùn)行下,看效果:

tableview header方案

看示意圖,我們可以看到整個(gè)tableview都在移動(dòng),而不是我們效果圖那種的樣式,在往下滾動(dòng)的時(shí)候,頭部的控件是不會(huì)網(wǎng)下移動(dòng)的,但是利用tableview的headerView進(jìn)行布局的方案是不成功的。

UIViewController 方案

我們首先在view上放置一個(gè)tableview和UIView(放置頭部的那些圖片)。

頁面的層級(jí)

以上都是在storyboard中操作的。


UIViewController方案添加header

以上的效果圖中可以看到頭部的headerView沒有類似于tableview的headerView那種滾動(dòng)的時(shí)候出現(xiàn)下移的情況。所以這種方式是可行的。
但是我們還需要設(shè)置tableview的偏移量,因?yàn)閳D片的顯示,遮擋住了我們的列表,所以需要設(shè)置一個(gè)偏移量:

    self.tableView.contentInset = UIEdgeInsetsMake(244, 0, 0, 0);

導(dǎo)航欄的一些細(xì)節(jié)處理

導(dǎo)航欄的文字,在剛開始出現(xiàn)的時(shí)候是需要隱藏掉的,

    //設(shè)置標(biāo)題
    UILabel *title = [[UILabel alloc] init];
    title.text = @"個(gè)人主頁";
    [title sizeToFit];
    // 開始的時(shí)候看不見,所以alpha值為0
    title.textColor = [UIColor colorWithWhite:0 alpha:0];
    self.navigationItem.titleView = title;

雖然我們已經(jīng)把文字隱藏掉了,但是已進(jìn)入到控制器,我們還是能看到導(dǎo)航欄,所以我們需要在進(jìn)入到控制器的時(shí)候隱藏掉,就在storyboard中進(jìn)行設(shè)置就可以了,選中控制器:


隱藏導(dǎo)航欄

把top Bar的設(shè)置改為None就可以了。

實(shí)現(xiàn)滾動(dòng)隱藏或顯示導(dǎo)航欄

我們知道tableview是繼承自scrollView的,所以有個(gè)-scrollViewDidScroll:方法中可以拿到tableview的滾動(dòng)。而且當(dāng)調(diào)用contentInset會(huì)自動(dòng)調(diào)用-scrollViewDidScroll:
我們可以這個(gè)方法中監(jiān)聽到scrollView的偏移量:

#pragma mark - scrollview
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    NSLog(@"%f", scrollView.contentOffset.y); //  原始偏移的位置是-244
}

所以導(dǎo)航欄的一些控制操作就在這個(gè)方法中進(jìn)行實(shí)現(xiàn)。
我們需要注意到的是,當(dāng)整個(gè)頁面上移到一定的位置的時(shí)候,就不在上移了,因?yàn)樾枰魤?4的位置給導(dǎo)航欄進(jìn)行顯示。也就是說這個(gè)顯示圖片這部分上移到一定的位置就不在移動(dòng)了。
我們需要改變這個(gè)控件的高度,那么就需要修改這個(gè)控件高度的約束,所以就需要拖個(gè)約束到控制器中。

// 頭部展示高度約束
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *imageHeight;

計(jì)算頭部的高度:

    CGFloat offset = scrollView.contentOffset.y - oriOfftY;
    CGFloat imgH = oriHeight - offset;
    if (imgH < 64) {
        // 當(dāng)上移到距離頂部小于64的時(shí)候,就不在移動(dòng)了。
        imgH = 64;
    }
    self.imageHeight.constant = imgH;
上移、下移
到此我們就需要處理透明度漸變的問題了。

由效果圖可以知道,整個(gè)頁面上移到一定的距離,就會(huì)完全顯示出導(dǎo)航欄,下移一定的距離,導(dǎo)航欄就會(huì)消失掉。

    //透明度
    //找最大值/
    CGFloat alpha = offset * 1 / 136.0;   // (200 - 64) / 136.0f
    if (alpha >= 1) {
        // 透明度最大值
        alpha = 0.99;
    }

設(shè)置文字:

    //拿到標(biāo)題 標(biāo)題文字的隨著移動(dòng)高度的變化而變化
    UILabel *titleL = (UILabel *)self.navigationItem.titleView;
    titleL.textColor = [UIColor colorWithWhite:0 alpha:alpha];

最后一步就是修改導(dǎo)航欄的背景的漸變效果:

    //把顏色生成圖片
    UIColor *alphaColor = [UIColor colorWithWhite:1 alpha:alpha];
    //把顏色生成圖片
    UIImage *alphaImage = [UIImage imageWithColor:alphaColor];
    //修改導(dǎo)航條背景圖片
    [self.navigationController.navigationBar setBackgroundImage:alphaImage forBarMetrics:UIBarMetricsDefault];

-imageWithColor :這個(gè)方法是UIImage的一個(gè)分類中的方法,專門就是把顏色轉(zhuǎn)換成圖片的方法:

// 顏色轉(zhuǎn)為圖片
+ (UIImage *)imageWithColor:(UIColor *)color {
    CGRect rect = CGRectMake(0, 0, 1.0f, 1.0f);
    // 開啟位圖上下文
    UIGraphicsBeginImageContext(rect.size);
    // 開啟上下文
    CGContextRef ref = UIGraphicsGetCurrentContext();
    // 使用color演示填充上下文
    CGContextSetFillColorWithColor(ref, color.CGColor);
    // 渲染上下文
    CGContextFillRect(ref, rect);
    // 從上下文中獲取圖片
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    // 結(jié)束上下文
    UIGraphicsEndImageContext();
    return image;
}

以上基本完成了想要的效果圖的功能了。
代碼傳送門,如果有幫助你的話,GitHub上給個(gè)贊唄!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,153評(píng)論 4 61
  • 大家好,我今天想說說a的故事。 希望能對一些人能有一些小小的幫助。 a并不是什么大人物,只是一個(gè)普通得不能再普通的...
    imBarbara閱讀 181評(píng)論 0 0
  • 馬背上的民族, 弓箭,牧羊,滾打,食肉 草原上的群狼, 忍耐,智慧,協(xié)作,奔放 狼守護(hù)著草原, 控制黃羊的數(shù)量,避...
    月亭閱讀 581評(píng)論 12 8

友情鏈接更多精彩內(nèi)容