iOS 隱藏導(dǎo)航欄下的1px黑色線條(runtime)

最近老板有個(gè)需求,需要把項(xiàng)目中所有的線條都給去掉,包括導(dǎo)航欄上的那根黑線,本來這個(gè)需求也很正常.可是我們的項(xiàng)目時(shí)間比較久遠(yuǎn)了,所以有的控制器繼承了基類,而有的則沒有,難道我需要在每個(gè)控制器里面都寫一遍隱藏的代碼么?特別是在一個(gè)需求多變的公司,假如哪次老板說需要這條線了,那我得重來一次么.不過我不不太喜歡寫重復(fù)性的代碼,所以就開始著手解決這件事了.

第一種:

由于1px的黑色線條是個(gè)黑色陰影圖片,所以我們可以通過設(shè)置這張圖片去讓它隱藏或者更換顏色.

①全局設(shè)置

//兩句話需要配合使用才有效
[[UINavigationBar appearance] setBackgroundImage:[UIImage imageNamed:@"white.jpg"] forBarPosition:UIBarPositionAny barMetrics:UIBarMetricsDefault];
[[UINavigationBar appearance] setShadowImage:[UIImage new]];

這是一種比較官方的一種寫法,不過這種方法會(huì)修改navigationBar的translucent(半透明)屬性,這個(gè)屬性會(huì)影響到我們的界面布局.
接下來我通過一個(gè)demo去驗(yàn)證它,我創(chuàng)建了兩個(gè)ViewController,分別對應(yīng)兩個(gè)UINavigationController.FirstVC采用了StoryBoard生成的界面,而ThirdVC則是通過代碼生成的,當(dāng)我們在AppDelegate.m中使用了上述方法后:

通過SB生成的導(dǎo)航控制器

通過代碼生成的導(dǎo)航控制器

UI層級(jí)

從圖片我們可以發(fā)現(xiàn),使用了修改圖片來達(dá)到隱藏線條的目的是完全可行的.但是,在SB中可能不會(huì)有太 大影響,不過在非SB的布局中,我們發(fā)現(xiàn)view的渲染是從導(dǎo)航欄的底部開始的,也是說View的Y點(diǎn)為64,所以說在該視圖上的控件的Frame也會(huì)改變.如果說我們在該界面有一個(gè)隱藏和顯示導(dǎo)航欄的操作,出現(xiàn)的后果則是:

//導(dǎo)航欄顯示下的Frame
self.view.frame = CGRectMake(0, 64, 375, 603);
//導(dǎo)航欄隱藏下的Frame
self.view.frame = CGRectMake(0, 0, 375, 667);

不過既然是問題,那就有解決的辦法,我們可以通過設(shè)置translucentYES就可以解決了,這時(shí)候View的布局會(huì)充滿全屏.

②單頁面設(shè)置

-(void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:@"white.jpg"] forBarMetrics:UIBarMetricsDefault];
    [self.navigationController.navigationBar setShadowImage:[UIImage new]];
}
-(void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    [self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:@"white.jpg"] forBarMetrics:UIBarMetricsDefault];
    [self.navigationController.navigationBar setShadowImage:nil];
}

第二種:

由于第一種的方法讓我項(xiàng)目中的VC出現(xiàn)了各種各樣的問題,而我又不想一個(gè)個(gè)去改,所以又有了接下來的辦法.我們可以通過遍歷導(dǎo)航欄的子控件,尋找到這個(gè)黑色線條,在合適的時(shí)候隱藏或者顯示,這時(shí)候我們就不會(huì)改變UINavigationBartranslucent了,也不會(huì)影響我們視圖的布局.

①單頁面設(shè)置

viewWillAppear:或者viewWillDisappear:中調(diào)用hideNavigationBarBottomLine:方法就可以完成對線條的隱藏或顯示.

-(void)hideNavigationBarBottomLine:(BOOL)hidden{
    //iOS10及以上的隱藏方法
    if ([UIDevice currentDevice].systemVersion.floatValue >= 10.0) {
        if ([self.navigationController.navigationBar respondsToSelector:@selector(setBackgroundImage:forBarMetrics:)]) {
            NSArray *list=self.navigationController.navigationBar.subviews;
            for (id obj in list) {
                //10.0的系統(tǒng)字段不一樣
                UIView *view =   (UIView*)obj;
                for (id obj2 in view.subviews) {
                    if ([obj2 isKindOfClass:[UIImageView class]]) {
                        UIImageView *image =  (UIImageView*)obj2;
                        if (image.frame.size.height <= 1) {
                            image.hidden = hidden;
                        }
                    }
                    
                    if ([obj2 isKindOfClass:[UIView class]]) {
                        UIView *view2 = (UIView *)obj2;
                        if (view2.frame.size.height <= 1) {
                            view2.hidden = hidden;
                        }
                    }
                }
            }
            
        }
        
        return;
    }
    //iOS10以下的隱藏方法
    if ([self.navigationController.navigationBar respondsToSelector:@selector(setBackgroundImage:forBarMetrics:)]){
        NSArray *list = self.navigationController.navigationBar.subviews;
        for (id obj in list) {
            if ([obj isKindOfClass:[UIImageView class]]) {
                UIImageView *imageView = (UIImageView *)obj;
                NSArray *list2 = imageView.subviews;
                for (id obj2 in list2) {
                    if ([obj2 isKindOfClass:[UIImageView class]]) {
                        UIImageView *imageView2 = (UIImageView *)obj2;
                        if (imageView2.frame.size.height <= 1) {
                            imageView2.hidden = hidden;
                        }
                    }
                    if ([obj2 isKindOfClass:[UIView class]]) {
                        UIView *view2 = (UIView *)obj2;
                        if (view2.frame.size.height <= 1) {
                            view2.hidden = hidden;
                        }
                    }
                }
            }
        }
    }
}

②最終方案(全局設(shè)置)

but,之前提過,因?yàn)椴幌雽懼貜?fù)性的代碼,所以才來折騰的,當(dāng)時(shí)就想,如果項(xiàng)目中所有的類都繼承了基類該多好啊,在基類的viewWillAppear:或者viewWillDisappear:中改一次就好了.想到這里,我突然想起來有一個(gè)方法可以每次都能調(diào)用這些方法,那就是runtime.我們可以寫一個(gè)UIViewController的類別,通過runtime我們可以獲取到UIViewController生命周期方法,在viewDidLoad中,我們只用寫一次代碼就可以了,后續(xù)的視圖控制器只要在生命周期中,都會(huì)到類別中去掉用隱藏的方法,方便又快捷,不要寫大量重復(fù)性的代碼.并且哪次老板需要顯示線條的時(shí)候,只要把這個(gè)類別移除就可以了,不用涉及到項(xiàng)目中其他類的操作.對于oc運(yùn)行時(shí)特性不了解的自行百度,具體的實(shí)現(xiàn)思路如下:

通過重寫NSObject類都有的Load方法,使用runtime替換系統(tǒng)的viewDidLoad方法為自己的hide_viewDidLoad方法.

+(void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Class class = [self class];
        
        SEL originalSelector1 = @selector(viewDidLoad);
        SEL swizzledSelector1 = @selector(hide_viewDidLoad);
        
        Method originalMethod1 = class_getInstanceMethod(class, originalSelector1);
        Method swizzledMethod1 = class_getInstanceMethod(class, swizzledSelector1);
        
        BOOL didAddMethod =
        class_addMethod(class,
                        originalSelector1,
                        method_getImplementation(swizzledMethod1),
                        method_getTypeEncoding(swizzledMethod1));
        
        if (didAddMethod) {
            class_replaceMethod(class,
                                swizzledSelector1,
                                method_getImplementation(originalMethod1),
                                method_getTypeEncoding(originalMethod1));
            
        } else {
            method_exchangeImplementations(originalMethod1, swizzledMethod1);
        }
    });
}

在替換的方法中寫我們相應(yīng)的需求:

-(void)hide_viewDidLoad {
    [self hide_viewDidLoad];
    
    if (self.navigationController) {
        [self hideNavigationBarBottomLine:YES];
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末拗胜,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子莽囤,更是在濱河造成了極大的恐慌榴芳,老刑警劉巖闲先,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件辜荠,死亡現(xiàn)場離奇詭異琼开,居然都是意外死亡养交,警方通過查閱死者的電腦和手機(jī)精算,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來碎连,“玉大人灰羽,你說我怎么就攤上這事。” “怎么了廉嚼?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵玫镐,是天一觀的道長。 經(jīng)常有香客問我怠噪,道長恐似,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任傍念,我火速辦了婚禮矫夷,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘憋槐。我一直安慰自己双藕,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布阳仔。 她就那樣靜靜地躺著忧陪,像睡著了一般。 火紅的嫁衣襯著肌膚如雪驳概。 梳的紋絲不亂的頭發(fā)上赤嚼,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天,我揣著相機(jī)與錄音顺又,去河邊找鬼更卒。 笑死,一個(gè)胖子當(dāng)著我的面吹牛稚照,可吹牛的內(nèi)容都是我干的蹂空。 我是一名探鬼主播,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼果录,長吁一口氣:“原來是場噩夢啊……” “哼上枕!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起弱恒,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤辨萍,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后返弹,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體锈玉,經(jīng)...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年义起,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了拉背。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,100評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡默终,死狀恐怖椅棺,靈堂內(nèi)的尸體忽然破棺而出犁罩,到底是詐尸還是另有隱情,我是刑警寧澤两疚,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布床估,位于F島的核電站,受9級(jí)特大地震影響鬼雀,放射性物質(zhì)發(fā)生泄漏顷窒。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一源哩、第九天 我趴在偏房一處隱蔽的房頂上張望鞋吉。 院中可真熱鬧,春花似錦励烦、人聲如沸谓着。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽赊锚。三九已至,卻和暖如春屉栓,著一層夾襖步出監(jiān)牢的瞬間舷蒲,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工友多, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留牲平,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓域滥,卻偏偏與公主長得像纵柿,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子启绰,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,834評論 2 345

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,516評論 25 707
  • *7月8日上午 N:Block :跟一個(gè)函數(shù)塊差不多昂儒,會(huì)對里面所有的內(nèi)容的引用計(jì)數(shù)+1,想要解決就用__block...
    炙冰閱讀 2,473評論 1 14
  • 在中國古代陶瓷史中委可,有一個(gè)一直被傳說和迷霧籠罩著的古窯渊跋,這就是五代十國時(shí)期出現(xiàn)的官窯——柴窯。但不同于其他官窯的是...
    丑小蟲閱讀 1,701評論 3 7
  • AR EasyAR iOS的SDK功能: 匹配場景圖片着倾,在匹配成功的圖片上加載圖像拾酝,3D模型,視頻屈呕; EasyAR...
    白菜松閱讀 3,855評論 1 6
  • 嫁錯(cuò)一個(gè)女虎眨,白養(yǎng)二十年。 01 林意涵是臺(tái)大四年級(jí)日文系的學(xué)生,為了提高日文水平嗽桩,她經(jīng)常上日本的臉書岳守,還交到了一個(gè)...
    江湖覓道閱讀 424評論 0 0