iOS-TabBar中間凸起點(diǎn)擊完全有反應(yīng)

  • 先看下效果
仿閑魚.png
  • 為什么還要繼續(xù)說這個(gè)內(nèi)容呢阀捅?
  • 前一段微博上很火的tabbar封裝大賽想必大家都知道吧,各位大神盡其所能
  • 自己正在仿寫閑魚锋爪,看了網(wǎng)上一些朋友寫的關(guān)于tabbar中間按鈕的處理水泉,發(fā)現(xiàn)關(guān)于處理中間按鈕的點(diǎn)擊這塊有點(diǎn)模糊
  • 個(gè)人估計(jì)是大家在寫這一塊的時(shí)候忽略了這個(gè)細(xì)節(jié)
    • 有的是中間按鈕凸起的部分點(diǎn)擊沒有反應(yīng),按鈕其他地方可以點(diǎn)擊
    • 有的是中間凸起按鈕可以完全點(diǎn)擊了掏婶,但是沒有做細(xì)節(jié)處理啃奴,導(dǎo)致push到其他頁(yè)面,在和凸起按鈕同樣的位置還可以被點(diǎn)擊雄妥,而且點(diǎn)擊效果和點(diǎn)擊凸起按鈕效果是一樣的
    • 還有的是雖然實(shí)現(xiàn)了功能最蕾,但是處理方法上并不是很完善
因此決定熬夜寫下這篇文章,幫助有需要的朋友看一下
  • 突然感覺沒有什么可說的了老厌,哈哈揖膜,主要是我代碼里面已經(jīng)寫得非常詳細(xì)了,而且文字多了效果也不好

  • 簡(jiǎn)單的說下大致結(jié)構(gòu)和思路吧

  • tabbar的話也是遵循主流梅桩,自定義一個(gè)繼承自系統(tǒng)UITabbar的LBTabbar壹粟,然后用KVC和系統(tǒng)的進(jìn)行替換

  • 中間的凸起按鈕和tabbar內(nèi)部的子控件不是同一類型,是一個(gè)UIButton而已

  • 根據(jù)tabbar內(nèi)部子控件的類型去調(diào)整內(nèi)部子控件的位置宿百,從而騰出一個(gè)中間位置給凸起按鈕

  • 給tabbar弄一個(gè)代理趁仙,添加一個(gè)點(diǎn)擊中間凸起按鈕的代理方法,讓LBTabBarController成為它的代理垦页,實(shí)現(xiàn)對(duì)應(yīng)代理方法即可實(shí)現(xiàn)按鈕點(diǎn)擊

  • 如果對(duì)以上步驟有不清楚的地方可以看代碼或者隨時(shí)咨詢我哦雀费,這篇文字主要講的核心就是中間按鈕點(diǎn)擊
    1)要想監(jiān)聽整個(gè)發(fā)布按鈕的點(diǎn)擊,包括凸起部分點(diǎn)擊也有反應(yīng)痊焊,那么我是通過在自定義的LBTabbar內(nèi)部重寫- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)even方法來實(shí)現(xiàn)的
    2)我們都知道盏袄,凸起按鈕是自定義的LBTabbar的子控件,默認(rèn)情況下子控件尺寸如果超出父控件薄啥,那么超出的部分點(diǎn)擊是沒有反應(yīng)的
    3)hitTest這個(gè)方法就是專門返回一個(gè)處理響應(yīng)事件最合適view的辕羽,一般情況下我們不實(shí)現(xiàn)這個(gè)方法,默認(rèn)就是讓系統(tǒng)幫我們?nèi)ヅ袛嗵幚硎录憫?yīng)最合適的view垄惧,一旦我們想要改變一下這種情況刁愿,我們就需要通過重寫這個(gè)方法
    4)我們的需求是只要我們點(diǎn)擊的point在凸起按鈕的任何位置(無論是否超出tabbar)都可以有響應(yīng),那么我們首先需要判斷這個(gè)point是否在凸起按鈕自身上
    [self convertPoint:point toView:self.plusBtn]
    這句代碼就是將當(dāng)前tabbar的觸摸點(diǎn)轉(zhuǎn)換坐標(biāo)系到逊,轉(zhuǎn)換到凸起按鈕的身上铣口,它會(huì)生成一個(gè)新的點(diǎn),然后我們通過
    [self.plusBtn pointInside:newP withEvent:event]方法判斷如果這個(gè)新的點(diǎn)是在發(fā)布按鈕身上觉壶,那么處理點(diǎn)擊事件最合適的view就是發(fā)布按鈕脑题,否則直接讓系統(tǒng)幫我們處理點(diǎn)擊事件就可以了
    5)對(duì)了,這里還有一步也是非常關(guān)鍵铜靶,因?yàn)槲覀冎貙懥藢ふ易詈线mview的方法叔遂,那么我們還需要考慮什么情況下我們需要由我們自己選擇最合適的view,什么情況下不需要,所以我們需要加一個(gè)判斷if (self.isHidden == NO)掏熬,
    這句代碼代表了當(dāng)前頁(yè)面是有tabbar的,那么肯定是在導(dǎo)航控制器的根控制器頁(yè)面秒梅,這個(gè)時(shí)候就需要由我們自己選擇最合適的view旗芬,其他的push頁(yè)面直接讓系統(tǒng)選擇
    6)如果不做第五步判斷,bug就是由導(dǎo)航控制器的根控制器頁(yè)面push到其他頁(yè)面后捆蜀,點(diǎn)擊該頁(yè)面和tabbar凸起按鈕同樣的位置也會(huì)有反應(yīng)
    7)好了疮丛,該上關(guān)鍵代碼了

//重寫hitTest方法,去監(jiān)聽發(fā)布按鈕的點(diǎn)擊辆它,目的是為了讓凸出的部分點(diǎn)擊也有反應(yīng)
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {

    //這一個(gè)判斷是關(guān)鍵誊薄,不判斷的話push到其他頁(yè)面,點(diǎn)擊發(fā)布按鈕的位置也是會(huì)有反應(yīng)的锰茉,這樣就不好了
    //self.isHidden == NO 說明當(dāng)前頁(yè)面是有tabbar的呢蔫,那么肯定是在導(dǎo)航控制器的根控制器頁(yè)面
    //在導(dǎo)航控制器根控制器頁(yè)面,那么我們就需要判斷手指點(diǎn)擊的位置是否在發(fā)布按鈕身上
    //是的話讓發(fā)布按鈕自己處理點(diǎn)擊事件飒筑,不是的話讓系統(tǒng)去處理點(diǎn)擊事件就可以了
    if (self.isHidden == NO) {

        //將當(dāng)前tabbar的觸摸點(diǎn)轉(zhuǎn)換坐標(biāo)系片吊,轉(zhuǎn)換到發(fā)布按鈕的身上,生成一個(gè)新的點(diǎn)
        CGPoint newP = [self convertPoint:point toView:self.plusBtn];

        //判斷如果這個(gè)新的點(diǎn)是在發(fā)布按鈕身上协屡,那么處理點(diǎn)擊事件最合適的view就是發(fā)布按鈕
        if ( [self.plusBtn pointInside:newP withEvent:event]) {
            return self.plusBtn;
        }else{//如果點(diǎn)不在發(fā)布按鈕身上俏脊,直接讓系統(tǒng)處理就可以了
          return [super hitTest:point withEvent:event];
     }
   } 
    else {//tabbar隱藏了,那么說明已經(jīng)push到其他的頁(yè)面了肤晓,這個(gè)時(shí)候還是讓系統(tǒng)去判斷最合適的view處理就好了
        return [super hitTest:point withEvent:event];
    }
}
下面是排布tabbar里面的子控件的
- (void)layoutSubviews
{
    [super layoutSubviews];
    //系統(tǒng)自帶的按鈕類型是UITabBarButton爷贫,找出這些類型的按鈕,然后重新排布位置补憾,空出中間的位置
    Class class = NSClassFromString(@"UITabBarButton");

    self.plusBtn.size = CGSizeMake(self.plusBtn.currentBackgroundImage.size.width, self.plusBtn.currentBackgroundImage.size.height);

    self.plusBtn.centerX = self.centerX;
    //調(diào)整發(fā)布按鈕的中線點(diǎn)Y值
    self.plusBtn.centerY = self.height * 0.5 - 2*LBMagin ;


        UILabel *label = [[UILabel alloc] init];
        label.text = @"發(fā)布";
        label.font = [UIFont systemFontOfSize:11];
        [label sizeToFit];
        label.textColor = [UIColor grayColor];
        [self addSubview:label];
        label.centerX = self.plusBtn.centerX;
        label.centerY = CGRectGetMaxY(self.plusBtn.frame) + LBMagin ;



    int btnIndex = 0;
    for (UIView *btn in self.subviews) {//遍歷tabbar的子控件
        if ([btn isKindOfClass:class]) {//如果是系統(tǒng)的UITabBarButton漫萄,那么就調(diào)整子控件位置,空出中間位置
            //每一個(gè)按鈕的寬度==tabbar的五分之一
            btn.width = self.width / 5;

            btn.x = btn.width * btnIndex;

            btnIndex++;
            //如果是索引是2(從0開始的)盈匾,直接讓索引++卷胯,目的就是讓消息按鈕的位置向右移動(dòng),空出來發(fā)布按鈕的位置
            if (btnIndex == 2) {
                btnIndex++;
            }
            
        }
    }
}

  • OK威酒,結(jié)束了窑睁,不足之處歡迎大家指正,共同學(xué)習(xí)
    代碼地址
后續(xù)準(zhǔn)備寫一篇關(guān)于事件響應(yīng)和傳遞的文章葵孤,如果對(duì)于hitTest方法不是很熟悉的朋友可以后續(xù)看看担钮,個(gè)人感覺這塊也是面試常客尤仍,感謝支持
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末箫津,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌苏遥,老刑警劉巖饼拍,帶你破解...
    沈念sama閱讀 206,126評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異田炭,居然都是意外死亡师抄,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門教硫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來叨吮,“玉大人,你說我怎么就攤上這事瞬矩〔杓” “怎么了?”我有些...
    開封第一講書人閱讀 152,445評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵景用,是天一觀的道長(zhǎng)涵叮。 經(jīng)常有香客問我,道長(zhǎng)伞插,這世上最難降的妖魔是什么围肥? 我笑而不...
    開封第一講書人閱讀 55,185評(píng)論 1 278
  • 正文 為了忘掉前任,我火速辦了婚禮蜂怎,結(jié)果婚禮上穆刻,老公的妹妹穿的比我還像新娘。我一直安慰自己杠步,他們只是感情好氢伟,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評(píng)論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著幽歼,像睡著了一般朵锣。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上甸私,一...
    開封第一講書人閱讀 48,970評(píng)論 1 284
  • 那天诚些,我揣著相機(jī)與錄音,去河邊找鬼皇型。 笑死诬烹,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的弃鸦。 我是一名探鬼主播绞吁,決...
    沈念sama閱讀 38,276評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼唬格!你這毒婦竟也來了家破?” 一聲冷哼從身側(cè)響起颜说,我...
    開封第一講書人閱讀 36,927評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎汰聋,沒想到半個(gè)月后门粪,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,400評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡烹困,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評(píng)論 2 323
  • 正文 我和宋清朗相戀三年玄妈,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片韭邓。...
    茶點(diǎn)故事閱讀 37,997評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡措近,死狀恐怖溶弟,靈堂內(nèi)的尸體忽然破棺而出女淑,到底是詐尸還是另有隱情,我是刑警寧澤辜御,帶...
    沈念sama閱讀 33,646評(píng)論 4 322
  • 正文 年R本政府宣布鸭你,位于F島的核電站,受9級(jí)特大地震影響擒权,放射性物質(zhì)發(fā)生泄漏袱巨。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評(píng)論 3 307
  • 文/蒙蒙 一碳抄、第九天 我趴在偏房一處隱蔽的房頂上張望愉老。 院中可真熱鬧,春花似錦剖效、人聲如沸嫉入。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽咒林。三九已至,卻和暖如春爷光,著一層夾襖步出監(jiān)牢的瞬間垫竞,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評(píng)論 1 260
  • 我被黑心中介騙來泰國(guó)打工蛀序, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留欢瞪,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,423評(píng)論 2 352
  • 正文 我出身青樓徐裸,卻偏偏與公主長(zhǎng)得像引有,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子倦逐,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評(píng)論 2 345

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