iOS 类似QQ的popMenu

作者: CodeGeass | 来源:发表于2016-07-01 14:33 被阅读1915次

    .h

    @interface QQPopMenuView : UIView
    
    @property (nonatomic, copy) void (^hideHandle)();
    
    /**
     *  实例化方法
     *
     *  @param array  items,包含字典,字典里面包含标题(title)、图片名(imageName)
     *  @param width  宽度
     *  @param point  三角的顶角坐标(基于window)
     *  @param action 点击回调
     */
    - (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 点击回调
     */
    + (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];
            
            
            // 创建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];
        // 设置右上角为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 {
        // 设置背景色
        [[UIColor whiteColor] set];
        //拿到当前视图准备好的画板
        CGContextRef context = UIGraphicsGetCurrentContext();
        //利用path进行绘制三角形
        CGContextBeginPath(context);
        CGPoint point = _trianglePoint;
        // 设置起点
        CGContextMoveToPoint(context, point.x, point.y);
        // 画线
        CGContextAddLineToPoint(context, point.x - 10, point.y + 10);
        CGContextAddLineToPoint(context, point.x + 10, point.y + 10);
        CGContextClosePath(context);
        // 设置填充色
        [[UIColor whiteColor] setFill];
        // 设置边框颜色
        [[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
    

    调用

    [QQPopMenuView showWithItems:@[@{@"title":@"发起讨论",@"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

    相关文章

      网友评论

      • f7139db11dcd:哪一句调用了这个方法drawRect
        CodeGeass:@HZW_sister 这个是自动调用啊,本身初始化后调用
      • 669f4f27f444:有源码下载地址吗?
        CodeGeass:@tonylegend 哈哈,抱歉,我更新晚了,而且新的用tableView更好一些
        669f4f27f444:@tonylegend 早段学习你的思路,自己做了一个!:smile:谢谢啦!
        CodeGeass:@tonylegend 已更新,谢谢支持
      • Jupiter_Van:直接用uipopoverpresentationcontroller
        CodeGeass:@stupidDeepInTho iOS 8.0才支持
      • Zeke权:demo,源码,效果图
        CodeGeass:@熊格智障 不客气,我的问题,长时间没有上传
        Zeke权:@CodeGeass 谢谢
        CodeGeass:@熊格智障 已上传
      • 买火柴的小男孩:直接给个demo的连接 更方便 哈哈
      • 跳跳虾:没有源码,差评
        CodeGeass:@刘文强 那个只是一个不为空处理,你可以不要他,好吧,仔细看了一下,用到了一些东西没有说明
        跳跳虾:@CodeGeass 复制过去,很多地方报错,也不知道是什么,例如IsEmptyObject
        CodeGeass:@刘文强 不是给的源码吗
      • kinmo:这效果图很不错
        CodeGeass:@July丶ye :smile:
      • 谁是我我我:哈哈:smile:幽默
        CodeGeass:@谁是我我我 :smile:

      本文标题:iOS 类似QQ的popMenu

      本文链接:https://www.haomeiwen.com/subject/kpgfjttx.html