前言:弱者為什么執(zhí)拗榕茧?
? ? 大三下在學(xué)swift的時候,給一款A(yù)PP建過言客给,說他的APP返回按鈕在按鈕形狀下是一團(tuán)用押,換成圖片就好了。當(dāng)時沒學(xué)多久起愈,想的也十分天真只恨。對方很給力,下個版本就改了抬虽。等到自己學(xué)Objective-c實習(xí)遇到這個問題的時候官觅,發(fā)現(xiàn)用圖片的確可以,但是有個新問題阐污,返回手勢不起作用了休涤!這就很尷尬了!我一定要與“按鈕形狀”斗爭到底笛辟!
按鈕形狀
? ? iOS在7.1版本出的按鈕形狀功氨,目的是為了讓按鈕更加顯眼。
圖1~3分別是按鈕捷凄、UIBarButtonItem、TabBar的普通狀態(tài)和按鈕形狀狀態(tài)围来,可以輕松的發(fā)現(xiàn)跺涤,按鈕的按鈕形狀是文字下面多了個下劃線,UIBarButtonItem和TabBar仿佛是多了個背景顏色监透。
返回按鈕
? ? 我在實習(xí)的時候桶错,項目一剛開始是這么解決返回按鈕的:
[[UIBarButtonItem appearance] setBackButtonTitlePositionAdjustment:UIOffsetMake(0,-60)forBarMetrics:UIBarMetricsDefault];
把返回按鈕的title上移60,移除屏幕胀蛮,就剩下一個返回圖標(biāo)院刁。這個方法在非按鈕形狀下顯示沒問題,在按鈕形狀下粪狼,返回按鈕就是一團(tuán)退腥,如圖4,顯然不怎么美觀再榄,尤其是當(dāng)父控制器title比較長的時候狡刘。
? ? 之后我嘗試了多種辦法,比如不跟,在父控制器push子控制器的時候颓帝,把父控制器的title設(shè)置為空,但是當(dāng)pop回來時發(fā)現(xiàn)上一級控制器title沒了(當(dāng)然了,你把它設(shè)置為空的)购城;改進(jìn)吕座,在子控制器viewWillAppear的時候把設(shè)置自己的title,在父控制器viewDidDisapper的時候把父控制器title設(shè)置為空(要判斷是push還是pop瘪板,為什么就不說了吴趴,反正也不用這個方法),缺點(diǎn)是返回按鈕會閃一下;把返回按鈕換成圖片侮攀,缺點(diǎn)是側(cè)滑返回手勢沒了锣枝。為此我還研究了其他很多APP的返回按鈕、TabBar兰英、UIBarButtonItem撇叁,依然沒有結(jié)果。
? ? 沒辦法畦贸,只好去看本地頭文件里面簡短的介紹陨闹、官方API文檔。發(fā)現(xiàn)如下幾個東西:backItem薄坏、backBarButtonItem趋厉、navigationItem.title、navigationController.title胶坠、viewController.title君账。
backItem,只讀沈善,先不管乡数。
對于backBarButtonItem,頭文件中注釋說:
Bar button item to use for the back button in the child navigation item.
用于子控制器的返回按鈕矮瘟。哇塞瞳脓,一臉懵逼塑娇,從來沒用過這個呀澈侠。繼續(xù)看。
對于navigationItem.title埋酬,頭文件中注釋說:
Title when topmost on the stack. default is nil
當(dāng)控制器在棧頂?shù)臅r候顯示的標(biāo)題哨啃,默認(rèn)為空。說的十分明白写妥。
對于navigationController.title拳球,不好意思這個用command+左鍵找到的是UIAlertController.title,viewController.title點(diǎn)進(jìn)去也是一樣的珍特,原來navigationController的繼承ViewController的,可能鏈接有點(diǎn)錯誤祝峻。
對于viewController.title,頭文件中注釋說
Localized title for use by a parent controller.
懵逼,去看看官方開發(fā)者API文檔吧莱找。
? ? 先看backBarButtonItem,翻一下就是:的確是用來設(shè)置子控制器的返回按鈕酬姆,在當(dāng)其需要一個返回按鈕的時候。但默認(rèn)為空奥溺。當(dāng)它為空的時候辞色,會用navigationItem的title屬性來建一個返回按鈕,如果你想自定義圖片或者標(biāo)題的返回按鈕浮定,你可以賦值一個普通的BarButtonItem給backBarButtonItem來替換相满。
? ? 說的很明白,順著它給的超鏈接來看navigationItem.title,翻一下:說它擺在navigationBar的中間桦卒,默認(rèn)為空立美。當(dāng)一個控制器有子控制器,并且navigationItem.title為空的時候哇方灾,系統(tǒng)會用“back”來作為子控制器返回按鈕的text悯辙。
? ? 也許你平時是直接對viewController.title或者navigationController.title進(jìn)行賦值,發(fā)現(xiàn)顯示也是沒問題的迎吵,同時影響著父控制器頂部導(dǎo)航欄標(biāo)題和子控制器的返回按鈕的標(biāo)題躲撰,這又是怎么回事呢?
你可以在UINavigationController中The Left Item完善對返回按鈕的認(rèn)識击费,在The Middle Item可以看到對titleView拢蛋、title的解釋,我們重點(diǎn)來看title蔫巩。翻一下:如果沒有設(shè)置自定義titleView谆棱,那么navigation bar就是展示一個label包含viewController的默認(rèn)標(biāo)題。這個標(biāo)題是從自己的viewController的title屬性獲取的圆仔,如果你想自定義垃瞧,你可以設(shè)置navigationItem的title屬性。
最后來到了UIViewController.title,翻一下:用人可讀的語言設(shè)置title來描述你的view坪郭,如果viewController有navigation item 或者 tab-bar item个从,那么會都影響這個兩個的title。UINavigationController.title官方直接超鏈接的是UIViewController.title歪沃,故不建議對UINavigationController.title進(jìn)行操作嗦锐,如有需要,可以對UIViewController.title進(jìn)行操作沪曙。
好了奕污,到了這,也許有點(diǎn)亂液走,理一下碳默。ViewController的title屬性無疑擁有最高影響力贾陷,它影響自己控制的navigation item 和 tab-bar item的title;navigation item的title默認(rèn)為空嘱根,會先受titleView的影響昵宇,如果沒有自定義titleView才顯示ViewController.title,你也可以設(shè)置navigationItem.title來自定義標(biāo)題儿子,最終顯示后設(shè)置的那個標(biāo)題瓦哎。backBarButtonItem默認(rèn)為空,子控制器的返回按鈕的title受其影響柔逼,當(dāng)其為空時蒋譬,返回按鈕會去找navigation item的title,navigation item的title也為空是愉适,會顯示“back”犯助,中文顯示“返回”。
問:自定義了titleView维咸,同時設(shè)置了navigationItem.title或者viewController.title剂买,請問父控制器頂部導(dǎo)航欄顯示誰的標(biāo)題?子控制器的返回按鈕顯示什么title癌蓖。
答:父控制器顯示自定義titleView的瞬哼,子控制器返回按鈕顯示navigationItem.title或者viewController.title。
OK租副,說了這么多坐慰,為了達(dá)到我們初始目的,只需要自定義一個UIBarButtonItem賦值給父控制器的backBarButtonItem就行了用僧!經(jīng)測試结胀,只有title有效,action责循、Target無效糟港。有空的同學(xué)可以嘗試用- (instancetype)initWithCustomView:(UIView*)customView;來自定義返回按鈕樣式,反正我沒嘗試成功院仿。
那么秸抚,我們在平時開發(fā)中應(yīng)該對哪個設(shè)置標(biāo)題呢?看下官方建議或者打開你的storyBoard:
如圖5意蛀,官方建議是對NavigationItem進(jìn)行設(shè)置耸别,當(dāng)你額外需要健芭,你可以設(shè)置TitleView給NavigationItem县钥,比如帶屬性的文字、把title變成一個可交互的Button等等慈迈。
Button若贮、TabBar和UIBarButtonItem
解決完返回按鈕省有,還剩下button、TabBar和UIBarButtonItem的按鈕形狀谴麦。實習(xí)的時候蠢沿,由于找不到方法解決“按鈕形狀”,一是問題不好描述匾效,二是關(guān)注的人少舷蟀,我一度認(rèn)為按鈕形狀狀態(tài)下有下劃線的就是Button,背景有顏色的就是UIBarButtonItem面哼、TabBar野宜,因此我一度認(rèn)為微博、淘寶等客戶端是完全自定義了NavigationController魔策、TabBarController匈子,前者導(dǎo)航欄上的Item沒有下劃線、也沒有背景顏色闯袒,后者導(dǎo)航欄全都是下劃線虎敦,前者底部TabBar有下劃線沒有背景顏色,難道是用的Button政敢?真不愧大牛捌溽恪!當(dāng)然也有客戶TabBar在按鈕形狀狀態(tài)下不顯示背景顏色喷户、也沒有下劃線的擂橘,說明還是有方法的,更加堅定了我繼續(xù)研究的決心摩骨。
一次偶然的機(jī)會通贞,我用Reveal發(fā)現(xiàn)了TabBar在按鈕形狀下顯示背景顏色的view:
我欣喜若狂,只要把這個View設(shè)置一個透明色不就好了恼五,然后我就去找這個View昌罩,很遺憾,沒找到灾馒,卻找到了selectionIndicatorImage茎用,肯定是親戚!趕緊設(shè)置TabBarButton:
self.selectionIndicatorImage = [UIImage new];
我是自定義的TabBar睬罗,所以這樣設(shè)置的轨功。一運(yùn)行,哈哈容达,背景顏色果然不見了古涧!什么原理呢?
看下官方解釋吧selectionIndicatorImage花盐,翻一下:用這個屬性來自定義選擇圖片羡滑,你的圖片將顯示在TabBar底部但是呢隱藏在TabBar的Contents的下面菇爪。默認(rèn)為空,當(dāng)為空時柒昏,被選定時就是顯示高亮凳宙。沒跑了就是它,選擇指示器圖片职祷,但是官方也沒提按鈕形狀氏涩。我們可以用它來做點(diǎn)選中TabBar的效果。那么其他兩個呢有梆?
用Reveal看按鈕削葱,就看不出什么鬼了,怎么辦呢淳梦?TabBar是因為設(shè)置了一個Image析砸,那么Button呢會不會也這樣呢?抱著試一試的心態(tài):
[testButton setBackgroundImage:[UIImage new] forState:UIControlStateNormal];
然后爆袍,然后下劃線就沒了J追薄!陨囊!怎么回事弦疮?官方的對背景圖片的說明也未提及按鈕形狀/下劃線/高亮,可能和TabBar差不多吧蜘醋。那么對于UIBarButtonItem只需要initWithCustomView:一個帶有背景圖片的button胁塞,那么在按鈕形狀下就不再有背景顏色了。有種戛然而止的感覺压语。
總結(jié)
1啸罢、子控制器的返回按鈕title優(yōu)先來自父控制器的backBarButtonItem.title;
2胎食、backBarButtonItem默認(rèn)為空扰才,當(dāng)其為空,返回按鈕就去找NavigationItem.title厕怜;
3衩匣、ViewController.title會同時影響NavigationItem.title、tabBar的title粥航,如果有的話琅捏;
4、針對第三點(diǎn)递雀,后設(shè)置的那個會最終顯示出來
5柄延、針對第二點(diǎn),當(dāng)NavigationItem.title也為空時映之,返回按鈕顯示“back”拦焚,中文“返回”蜡坊;
6杠输、當(dāng)backBarButtonItem.title為空字符串時赎败,子控制器返回按鈕只顯示圖標(biāo),并且沒有按鈕形狀下的一塊背景顏色(修改NavigationItem的title不建議)蠢甲;
7僵刮、要修改控制器的頂部導(dǎo)航欄標(biāo)題建議對NavigationItem.title進(jìn)行修改;
8鹦牛、去除TabBar的按鈕形狀設(shè)置它的selectionIndicatorImage搞糕;
9、去除UIButton的按鈕形狀曼追,setBackgroundImage:[UIImage new] forState:UIControlStateNormal窍仰;
10、去除UIBarButtonItem的按鈕形狀礼殊,initWithCustomView:一個帶有背景圖片的button即可驹吮;
后記
寫完了,越寫到后面越發(fā)現(xiàn)一股弱者的氣息晶伦,希望能幫到人碟狞。拜了個拜。@徐星星去哪了