【iOS】帶箭頭的彈出菜單

前言

之前有在一些項(xiàng)目中用到過一些帶箭頭的彈出菜單试幽,其實(shí)這個(gè)樣式的UI組件還是比較常見的,QQ和微信虚青,支付寶等等很多App都有類似的UI組件涩咖,所以我把之前項(xiàng)目中的相關(guān)代碼抽取出來,然后做了個(gè)封裝级野,所有就有了今天這篇內(nèi)容页屠。
其實(shí)也不算直接封裝之前的代碼,之前的實(shí)現(xiàn)方式是用modal出控制器蓖柔,然后自定義轉(zhuǎn)場動(dòng)畫辰企,同時(shí)在轉(zhuǎn)場代理中通過 UIPresentationController 改變視圖的frame實(shí)現(xiàn)的,同時(shí)箭頭也是用一個(gè)帶箭頭的背景圖實(shí)現(xiàn)的况鸣。不過當(dāng)前封裝的這個(gè)UI視圖則是放棄了帶控制器的這種方式牢贸,是用純視圖的組合封裝來實(shí)現(xiàn)的。

實(shí)現(xiàn)效果

運(yùn)行效果.gif

使用方式

使用方式很簡單懒闷,先將CWPopMenu.h和CWPopMenu.m這兩個(gè)文件拖到項(xiàng)目里十减。
導(dǎo)入頭文件之后直接初始化并調(diào)用showMenu顯示
    self.menu = [[CWPopMenu alloc]initWithArrow:CGPointMake(self.view.frame.size.width-25, _sumHeight) menuSize:CGSizeMake(130, 200) arrowStyle:CWPopMenuArrowTopfooter];
    //代理是UITableView的代理方法
    _menu.dataSource = self;
    _menu.delegate = self;
    //設(shè)置菜單的背景色(默認(rèn)是白色)
    _menu.menuViewBgColor = [UIColor whiteColor];
    //YES代表使用動(dòng)畫
    [_menu showMenu:YES];
方法以及參數(shù)的意義
/**
 @param point 箭頭箭尖的坐標(biāo)
 @param size 菜單的視圖的大小
 @param position 箭頭的方位(同時(shí)決定縮放動(dòng)畫的錨點(diǎn))
 */
- (instancetype)initWithArrow:(CGPoint)point menuSize:(CGSize)size arrowStyle:(CWPopMenuArrowPosition)position;

//顯示 *屬性設(shè)置需要在show之前設(shè)置才會(huì)生效*
- (void)showMenu:(BOOL)animated;

//關(guān)閉
- (void)closeMenu:(BOOL)animated;
部分可設(shè)置的屬性
//箭頭在上或者下邊的前中后位置枚舉(從左到右)
typedef NS_ENUM(NSInteger, CWPopMenuArrowPosition) {
    CWPopMenuArrowTopHeader = 0,//默認(rèn)從0開始
    CWPopMenuArrowTopCenter,
    CWPopMenuArrowTopfooter,
    CWPopMenuArrowBottomHeader,
    CWPopMenuArrowBottomCenter,
    CWPopMenuArrowBottomfooter,
};
//箭頭方位的枚舉會(huì)決定箭頭在菜單視圖的位置栈幸,以及縮放動(dòng)畫的錨點(diǎn)位置

//菜單蒙版的透明度 default bgViewAlpha = 0.2;設(shè)置alpha屬性時(shí)會(huì)被bgAlpha接管
@property (nonatomic, assign)CGFloat bgAlpha;

//菜單背景色 default menuViewBgColor = [UIColor whiteColor];
@property (nonatomic, assign)UIColor *menuViewBgColor;

//菜單圓角 default menuRadius = 5.f;
@property (nonatomic, assign)CGFloat menuRadius;

//箭頭寬度 default arrowWidth = 15.f;
@property (nonatomic, assign)CGFloat arrowWidth;

//箭頭高度 default arrowHeight = 10.f;
@property (nonatomic, assign)CGFloat arrowHeight;
其實(shí)這個(gè)UI視圖是沒什么難度的東西,菜單核心視圖就是個(gè)UITableView帮辟,就是箭頭繪制要進(jìn)行各種判斷寫起來稍微麻煩點(diǎn)速址。

核心方法

//根據(jù)位置枚舉以及箭頭高度和寬度計(jì)算繪制箭頭的點(diǎn)
- (void)computeArrowPosition:(CWPopMenuArrowPosition)arrowPosition
{
    CGRect _menuFrame = _menuView.frame;
    CGFloat menuX = _menuFrame.origin.x;
    CGFloat menuY = _menuFrame.origin.y;
    CGFloat menuWidth = _menuFrame.size.width;
    CGFloat menuHeight = _menuFrame.size.height;
    
    switch (_arrowPosition) {
        case CWPopMenuArrowTopHeader:
        {
            CGPoint origin = CGPointMake(menuX+distance, menuY);
            CGPoint peak = CGPointMake(menuX+_arrowWidth*0.5 +distance, menuY-_arrowHeight);
            CGPoint terminus = CGPointMake(menuX+_arrowWidth+distance, menuY);
            [self drawArrowInLayer:origin peak:peak terminus:terminus];
        }
            
            break;
        case CWPopMenuArrowTopCenter:
        {
            CGPoint origin = CGPointMake(menuX+(menuWidth-_arrowWidth)*0.5, menuY);
            CGPoint peak = CGPointMake(menuX+menuWidth*0.5, menuY-_arrowHeight);
            CGPoint terminus = CGPointMake(menuX+(menuWidth+_arrowWidth)*0.5, menuY);
            [self drawArrowInLayer:origin peak:peak terminus:terminus];
        }
            break;
        case CWPopMenuArrowTopfooter:
        {
            CGPoint origin = CGPointMake(menuX+menuWidth-_arrowWidth-distance, menuY);
            CGPoint peak = CGPointMake(menuX+menuWidth-_arrowWidth*0.5-distance, menuY-_arrowHeight);
            CGPoint terminus = CGPointMake(menuX+menuWidth-distance, menuY);
            [self drawArrowInLayer:origin peak:peak terminus:terminus];
        }
            break;
        case CWPopMenuArrowBottomHeader:
        {
            CGPoint origin = CGPointMake(menuX+distance, menuY+menuHeight);
            CGPoint peak = CGPointMake(menuX+_arrowWidth*0.5+distance, menuY+menuHeight+_arrowHeight);
            CGPoint terminus = CGPointMake(menuX+_arrowWidth+distance, menuY+menuHeight);
            [self drawArrowInLayer:origin peak:peak terminus:terminus];
        }
            break;
        case CWPopMenuArrowBottomCenter:
        {
            CGPoint origin = CGPointMake(menuX+(menuWidth-_arrowWidth)*0.5, menuY+menuHeight);
            CGPoint peak = CGPointMake(menuX+menuWidth*0.5, menuY+menuHeight+_arrowHeight);
            CGPoint terminus = CGPointMake(menuX+(menuWidth+_arrowWidth)*0.5, menuY+menuHeight);
            [self drawArrowInLayer:origin peak:peak terminus:terminus];
        }
            break;
        case CWPopMenuArrowBottomfooter:
        {
            CGPoint origin = CGPointMake(menuX+menuWidth-_arrowWidth-distance, menuY+menuHeight);
            CGPoint peak = CGPointMake(menuX+menuWidth-_arrowWidth*0.5-distance, menuY+menuHeight+_arrowHeight);
            CGPoint terminus = CGPointMake(menuX+menuWidth-distance, menuY+menuHeight);
            [self drawArrowInLayer:origin peak:peak terminus:terminus];
        }
            break;
        default:
            
            break;
    }
}

//繪制箭頭
- (void)drawArrowInLayer:(CGPoint)origin peak:(CGPoint)peak terminus:(CGPoint)terminus{
    //定義畫圖的path
    self.shLayer = [[CAShapeLayer alloc]init];
    UIBezierPath *path = [[UIBezierPath alloc] init];
    _shLayer.fillColor = self.menuViewBgColor.CGColor;
    
    //path移動(dòng)到開始畫圖的位置
    [path moveToPoint:origin];
    [path addLineToPoint:peak];
    [path addLineToPoint:terminus];
    _shLayer.path = [path CGPath];
    
    //關(guān)閉path
    [path closePath];
    [self.layer addSublayer:_shLayer];
}

寫在最后

希望對看到的人有些幫助,如果各位看官覺得有所幫助請點(diǎn)個(gè)贊由驹。

PS:附上demo傳送門

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末芍锚,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子蔓榄,更是在濱河造成了極大的恐慌并炮,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件甥郑,死亡現(xiàn)場離奇詭異逃魄,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)澜搅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進(jìn)店門伍俘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人勉躺,你說我怎么就攤上這事癌瘾。” “怎么了饵溅?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵妨退,是天一觀的道長。 經(jīng)常有香客問我蜕企,道長咬荷,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任糖赔,我火速辦了婚禮萍丐,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘放典。我一直安慰自己逝变,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布奋构。 她就那樣靜靜地躺著壳影,像睡著了一般。 火紅的嫁衣襯著肌膚如雪弥臼。 梳的紋絲不亂的頭發(fā)上宴咧,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天,我揣著相機(jī)與錄音径缅,去河邊找鬼掺栅。 笑死烙肺,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的氧卧。 我是一名探鬼主播桃笙,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼沙绝!你這毒婦竟也來了搏明?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤闪檬,失蹤者是張志新(化名)和其女友劉穎星著,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體粗悯,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡虚循,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了为黎。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片邮丰。...
    茶點(diǎn)故事閱讀 38,622評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡行您,死狀恐怖铭乾,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情娃循,我是刑警寧澤炕檩,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站捌斧,受9級特大地震影響笛质,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜捞蚂,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一妇押、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧姓迅,春花似錦敲霍、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至解寝,卻和暖如春扩然,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背聋伦。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工夫偶, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留界睁,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓兵拢,卻偏偏與公主長得像晕窑,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子卵佛,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,490評論 2 348

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

  • 我們常常說的一句話就是希望你過的比我好截汪,是真的嗎疾牲? 可能說出來的時(shí)候的確是發(fā)自內(nèi)心的,然而她真的過的比你好的時(shí)候衙解,...
    淺笑舒眉閱讀 255評論 0 1
  • 幾乎所有推進(jìn)人類進(jìn)步的創(chuàng)新蚓峦,都來源于偶然的不確定性事件舌剂,比如蘋果所采用的觸屏。 不確定性事件暑椰,由于它以前從未有過霍转,...
    鄭宇辰閱讀 604評論 1 2
  • 生態(tài)學(xué)meta分析開源軟件OpenMEE介紹 落后的統(tǒng)計(jì)方法以及無法升級的確定限制了生態(tài)學(xué)研究對過去meta分析軟...
    cppcwang閱讀 8,169評論 3 6
  • 心里會(huì)不定期更新一條計(jì)劃行走的路線,有時(shí)會(huì)醞釀很久一汽,有時(shí)只是一瞬間的事情避消。 去湘西只是兩分鐘就決定下來的事情。有一...
    冷小茶閱讀 625評論 6 12