iOS 類似QQ的popMenu

.h

@interface QQPopMenuView : UIView

@property (nonatomic, copy) void (^hideHandle)();

/**
 *  實例化方法
 *
 *  @param array  items灵寺,包含字典殖卑,字典里面包含標題(title)识颊、圖片名(imageName)
 *  @param width  寬度
 *  @param point  三角的頂角坐標(基于window)
 *  @param action 點擊回調(diào)
 */
- (instancetype)initWithItems:(NSArray <NSDictionary *>*)array
                        width:(CGFloat)width
             triangleLocation:(CGPoint)point
                       action:(void(^)(NSInteger index))action;

/**
 *  類方法展示
 *
 *  @param array  items浩嫌,包含字典钠糊,字典里面包含標題(title)垫言、圖片名(imageName)
 *  @param width  寬度
 *  @param point  三角的頂角坐標(基于window)
 *  @param action 點擊回調(diào)
 */
+ (void)showWithItems:(NSArray <NSDictionary *>*)array
                width:(CGFloat)width
     triangleLocation:(CGPoint)point
               action:(void(^)(NSInteger index))action;

- (void)show;
- (void)hide;

@end

.m

#import "QQPopMenuView.h"
#import "PopMenuTableViewCell.h"

#define SCREEN_WIDTH [UIScreen mainScreen].bounds.size.width

static CGFloat const kCellHeight = 44;

@interface QQPopMenuView ()<UITableViewDelegate,UITableViewDataSource,UIGestureRecognizerDelegate>
@property (nonatomic, strong) UITableView *tableView;
@property (nonatomic, strong) NSArray *tableData;
@property (nonatomic, assign) CGPoint trianglePoint;
@property (nonatomic, copy) void(^action)(NSInteger index);
@end

@implementation QQPopMenuView

- (instancetype)initWithItems:(NSArray <NSDictionary *>*)array
                        width:(CGFloat)width
             triangleLocation:(CGPoint)point
                       action:(void(^)(NSInteger index))action
{
    if (array.count == 0) {
        return nil;
    }
    
    if (self = [super init]) {
        self.frame = [UIScreen mainScreen].bounds;
        self.backgroundColor = [UIColor colorWithWhite:0 alpha:0.2];
        self.alpha = 0;
        _tableData = [array copy];
        _trianglePoint = point;
        self.action = action;
        
        
        // 添加手勢
        UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap)];
        tap.delegate = self;
        [self addGestureRecognizer:tap];
        
        
        // 創(chuàng)建tableView
        _tableView = [[UITableView alloc] initWithFrame:CGRectMake(SCREEN_WIDTH - width - 5, point.y + 10, width, kCellHeight * array.count) style:UITableViewStylePlain];
        _tableView.delegate = self;
        _tableView.dataSource = self;
        _tableView.layer.masksToBounds = YES;
        _tableView.layer.cornerRadius = 5;
        _tableView.scrollEnabled = NO;
        _tableView.rowHeight = kCellHeight;
        [_tableView registerNib:[UINib nibWithNibName:@"PopMenuTableViewCell" bundle:nil] forCellReuseIdentifier:@"PopMenuTableViewCell"];
        [self addSubview:_tableView];
    
    }
    return self;
}

+ (void)showWithItems:(NSArray <NSDictionary *>*)array
                width:(CGFloat)width
     triangleLocation:(CGPoint)point
               action:(void(^)(NSInteger index))action
{
    QQPopMenuView *view = [[QQPopMenuView alloc] initWithItems:array width:width triangleLocation:point action:action];
    [view show];
}

- (void)tap {
    [self hide];
}

#pragma mark - UIGestureRecognizerDelegate
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    if ([touch.view isKindOfClass:NSClassFromString(@"UITableViewCellContentView")]) {
        return NO;
    }
    return YES;
}

#pragma mark - Show or Hide
- (void)show {
    [[UIApplication sharedApplication].keyWindow addSubview:self];
    // 設(shè)置右上角為transform的起點(默認是中心點)
    _tableView.layer.position = CGPointMake(SCREEN_WIDTH - 5, _trianglePoint.y + 10);
    // 向右下transform
    _tableView.layer.anchorPoint = CGPointMake(1, 0);
    _tableView.transform = CGAffineTransformMakeScale(0.0001, 0.0001);
    [UIView animateWithDuration:0.2 animations:^{
        self.alpha = 1;
        _tableView.transform = CGAffineTransformMakeScale(1.0, 1.0);
    }];
}

- (void)hide {
    [UIView animateWithDuration:0.2 animations:^{
        self.alpha = 0;
        _tableView.transform = CGAffineTransformMakeScale(0.0001, 0.0001);
    } completion:^(BOOL finished) {
        [_tableView removeFromSuperview];
        [self removeFromSuperview];
        if (self.hideHandle) {
            self.hideHandle();
        }
    }];
}

#pragma mark - Draw triangle
- (void)drawRect:(CGRect)rect {
    // 設(shè)置背景色
    [[UIColor whiteColor] set];
    //拿到當(dāng)前視圖準備好的畫板
    CGContextRef context = UIGraphicsGetCurrentContext();
    //利用path進行繪制三角形
    CGContextBeginPath(context);
    CGPoint point = _trianglePoint;
    // 設(shè)置起點
    CGContextMoveToPoint(context, point.x, point.y);
    // 畫線
    CGContextAddLineToPoint(context, point.x - 10, point.y + 10);
    CGContextAddLineToPoint(context, point.x + 10, point.y + 10);
    CGContextClosePath(context);
    // 設(shè)置填充色
    [[UIColor whiteColor] setFill];
    // 設(shè)置邊框顏色
    [[UIColor whiteColor] setStroke];
    // 繪制路徑
    CGContextDrawPath(context, kCGPathFillStroke);
}

#pragma mark - UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return self.tableData.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    PopMenuTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"PopMenuTableViewCell" forIndexPath:indexPath];
    NSDictionary *dic = _tableData[indexPath.row];
    cell.leftImageView.image = [UIImage imageNamed:dic[@"imageName"]];
    cell.titleLabel.text = dic[@"title"];
    cell.selectionStyle = UITableViewCellSelectionStyleNone;
    cell.layoutMargins = UIEdgeInsetsZero;
    cell.separatorInset = UIEdgeInsetsZero;
    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    [self hide];
    if (_action) {
        _action(indexPath.row);
    }
}

@end

調(diào)用

[QQPopMenuView showWithItems:@[@{@"title":@"發(fā)起討論",@"imageName":@"popMenu_createChat"},
                                   @{@"title":@"掃描名片",@"imageName":@"popMenu_scanCard"},
                                   @{@"title":@"寫日報",@"imageName":@"popMenu_writeReport"},
                                   @{@"title":@"外勤簽到",@"imageName":@"popMenu_signIn"}]
                           width:130
                triangleLocation:CGPointMake([UIScreen mainScreen].bounds.size.width-30, 64+5)
                          action:^(NSInteger index) {
                              NSLog(@"點擊了第%ld行",index);
    }];

效果圖

screenshot.gif

Demo

https://github.com/guanzhendong/QQPopMenuView

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市瞻讽,隨后出現(xiàn)的幾起案子鸳吸,更是在濱河造成了極大的恐慌,老刑警劉巖速勇,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件晌砾,死亡現(xiàn)場離奇詭異,居然都是意外死亡烦磁,警方通過查閱死者的電腦和手機养匈,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來个初,“玉大人乖寒,你說我怎么就攤上這事≡耗纾” “怎么了?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵磅轻,是天一觀的道長珍逸。 經(jīng)常有香客問我逐虚,道長,這世上最難降的妖魔是什么谆膳? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任叭爱,我火速辦了婚禮,結(jié)果婚禮上漱病,老公的妹妹穿的比我還像新娘买雾。我一直安慰自己,他們只是感情好杨帽,可當(dāng)我...
    茶點故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布漓穿。 她就那樣靜靜地躺著,像睡著了一般注盈。 火紅的嫁衣襯著肌膚如雪晃危。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天老客,我揣著相機與錄音僚饭,去河邊找鬼。 笑死胧砰,一個胖子當(dāng)著我的面吹牛鳍鸵,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播尉间,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼偿乖,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了乌妒?” 一聲冷哼從身側(cè)響起汹想,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎撤蚊,沒想到半個月后古掏,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡侦啸,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年槽唾,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片光涂。...
    茶點故事閱讀 39,902評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡庞萍,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出忘闻,到底是詐尸還是另有隱情钝计,我是刑警寧澤,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站私恬,受9級特大地震影響债沮,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜本鸣,卻給世界環(huán)境...
    茶點故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一疫衩、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧荣德,春花似錦闷煤、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至饲宛,卻和暖如春皆愉,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背艇抠。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工幕庐, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人家淤。 一個月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓异剥,卻偏偏與公主長得像,于是被迫代替她去往敵國和親絮重。 傳聞我的和親對象是個殘疾皇子冤寿,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,843評論 2 354

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

  • afinalAfinal是一個android的ioc,orm框架 https://github.com/yangf...
    passiontim閱讀 15,429評論 2 45
  • 清唱第521篇 自從知道我工作10年已經(jīng)走過20多個國家青伤,不斷有人問我督怜,你哪有那么多時間,你哪有那么多錢狠角。 重復(fù)次...
    拉草莓的西瓜閱讀 417評論 4 2
  • 如果有來生号杠, 要做一片葉。 生則綠在枝頭丰歌, 死則委地成土姨蟋。 當(dāng)春天綠過樹丫, 夏天吻過群花立帖, 我只生長眼溶,長大。 當(dāng)...
    清昂閱讀 227評論 0 1
  • 本乃世家子 位尊枕無憂 奈何歷朝改 榮華付東流 嚴父被特務(wù) 慈母反壞右 尊兄發(fā)深山 弟妹年尚幼 一天三頓飯 全靠血...
    一默1520閱讀 775評論 3 13