早之前在项目中写了一个类似微信右上角下拉的菜单封装,但是是写死的,当时根本
没有考虑到去其他地方弹出这个东西,虽然看起来弹个窗出来很简单,但是你位子不确
定之后弹出来是有点麻烦的,反正我总是觉得,我们能想到的,老外早就想到了,多给自己弄点工具库,多看看源码,指不定哪天我也搞出一个库来,世界
上有项目经理这种东西,那就没有什么需求是不可能的,各位手头上多准备点工具还是非常有必要的。
先看图:
需求是这样的,点击分类的按钮,竟然不Push到另一个VC去,非要弹个窗出来
但是像我这样的读书人这么有素质的,心里肯定是这么想的
OK,废话不多说,各位看官,七龙珠我已经搜集起了,你们只要看神龙就行了
CMPopTipView:https://github.com/chrismiles/CMPopTipView
Show Time(UITableView,UICollectionView,UIImageView,UILabel都可弹)
哎呦,这妹子不错吧
Demo介绍
首先,新建一个工程,把Button创建出来,点击事件加上,先看属性
@interface ViewController () <CMPopTipViewDelegate,UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout,UITableViewDelegate,UITableViewDataSource> @property (nonatomic,strong) CMPopTipView *roundRectButtonPopTipView; @property (nonatomic,strong) NSMutableArray *dataSource; //!< collectionView的数据源 @property (nonatomic,strong) GroupList *list; //!< 请求回来的数据 @property (nonatomic,strong) UICollectionView *collectionView; @property (nonatomic,strong) UIImageView *imageView; @property (nonatomic,strong) UIImageView *imageView1; @property (weak, nonatomic) IBOutlet UILabel *middleLabel; @property (nonatomic,strong) NSMutableArray *visiblePopTipViews; //!< 可见的PopView @property (nonatomic,strong) id currentPopTipViewTarget; //!< 当前的按钮 @property (nonatomic,strong) UITableView *tableView; @property (nonatomic,strong) NSMutableArray *tableDataSource; @property (nonatomic,strong) UIButton *gotoCartButton; // NVBar的按钮 @end
所有非NavigationItemButton的点击事件
注:该方法可以获取到已加载数据的CollectionView的理论高度
height =
self.collectionView.collectionViewLayout.collectionViewContentSize.height;
- (IBAction)click:(UIButton *)sender { // 先dismiss之前的所有popView [self dismissAllPopTipViews]; // 当检测到是和之前一样的按钮,由于已经清空,那么不进行任何操作,也把容器清空,下次再点就可以下一波操作了 if (sender == self.currentPopTipViewTarget) { self.currentPopTipViewTarget = nil; } else { // 没有pop的时候,先计算出collectionView的高度 CGFloat height; if (sender.tag == 1000) { self.dataSource = [[NSMutableArray alloc] initWithArray:self.list.data.role]; [self.collectionView reloadData]; } else if (sender.tag == 1003) { self.dataSource = [[NSMutableArray alloc] initWithArray:self.list.data.list]; [self.collectionView reloadData]; } // 算高度 height = self.collectionView.collectionViewLayout.collectionViewContentSize.height; NSString *title = nil; NSString *msg = nil; CMPopTipView *popView; switch (sender.tag) { case 1000: self.collectionView.frame = CGRectMake(0, 0, 300, height); self.collectionView.alwaysBounceVertical = YES; // 加载自定义View popView = [[CMPopTipView alloc] initWithCustomView:self.collectionView]; break; case 1001: msg = @"这是一个简单的Demo,希望大家看明白,能用在自己的项目中"; title = @"博主是逗逼"; // 加载title和Msg的混合 popView = [[CMPopTipView alloc] initWithTitle:title message:msg]; break; case 1002: self.imageView.frame = CGRectMake(0, 0, 350, 300); popView = [[CMPopTipView alloc] initWithCustomView:self.imageView]; break; case 1003: self.collectionView.frame = CGRectMake(0, 0, 300, height>400?400:height); self.collectionView.alwaysBounceVertical = YES; popView = [[CMPopTipView alloc] initWithCustomView:self.collectionView]; break; case 1004: msg = @"With groups, Xcode stores in the project a reference to each individual file."; title = @"博主我爱你"; popView = [[CMPopTipView alloc] initWithTitle:title message:msg]; break; case 1005: self.imageView1.frame = CGRectMake(0, 0, 350, 300); popView = [[CMPopTipView alloc] initWithCustomView:self.imageView1]; break; default: break; } popView.delegate = self; popView.cornerRadius = 5; // 是否有阴影 //popView.hasShadow = YES; // 是否有梯度 //popView.hasGradientBackground = NO; popView.backgroundColor = [UIColor colorWithRed:arc4random() % 256 / 255.0 green:arc4random() % 256 / 255.0 blue:arc4random() % 256 / 255.0 alpha:1]; popView.textColor = [UIColor colorWithRed:arc4random() % 256 / 255.0 green:arc4random() % 256 / 255.0 blue:arc4random() % 256 / 255.0 alpha:1]; // 0是Slide 1是pop 2是Fade但是有问题,用前两个就好了 popView.animation = arc4random() % 1; // 立体效果,默认是YES popView.has3DStyle = arc4random() % 1; // 是否点击任意位子就影藏 //popView.dismissTapAnywhere = YES; // 是否自定影藏 //[popView autoDismissAnimated:YES atTimeInterval:5.0]; [popView presentPointingAtView:sender inView:self.view animated:YES]; [self.visiblePopTipViews addObject:popView]; self.currentPopTipViewTarget = sender; } }
代理方法和销毁PopView的方法
// 点击的时候取消PopView - (void)dismissAllPopTipViews { while ([self.visiblePopTipViews count] > 0) { CMPopTipView *popTipView = [self.visiblePopTipViews objectAtIndex:0]; [popTipView dismissAnimated:YES]; [self.visiblePopTipViews removeObjectAtIndex:0]; } } // PopView的代理,当Pop消失的时候调用 - (void)popTipViewWasDismissedByUser:(CMPopTipView *)popTipView { [self dismissAllPopTipViews]; self.currentPopTipViewTarget = nil; NSLog(@"消失了"); self.roundRectButtonPopTipView = nil; }
下面是CMPopTipView的初始化属性,大家可自行修改测试
例如圆角cornerRadius是默认10,如果不需要圆角就可以去掉
// 默认值 //- (id)initWithFrame:(CGRect)frame //{ // if ((self = [super initWithFrame:frame])) { // // Initialization code // self.opaque = NO; // // _topMargin = 2.0; // _pointerSize = 12.0; // _sidePadding = 2.0; // _borderWidth = 1.0; // // self.textFont = [UIFont boldSystemFontOfSize:14.0]; // self.textColor = [UIColor whiteColor]; // self.textAlignment = NSTextAlignmentCenter; // self.backgroundColor = [UIColor colorWithRed:62.0/255.0 green:60.0/255.0 blue:154.0/255.0 alpha:1.0]; // self.has3DStyle = YES; // self.borderColor = [UIColor blackColor]; // self.hasShadow = YES; // self.animation = CMPopTipAnimationSlide; // self.dismissTapAnywhere = NO; // self.preferredPointDirection = PointDirectionAny; // self.hasGradientBackground = YES; // self.cornerRadius = 10.0; // } // return self; //}
然后,我们再看看给UINavigationBar上面的UIBarButtonItem的方法调用
其他逻辑方法都基本一致,只是调用的最终弹窗方法不同
popView presentPointingAtBarButtonItem: animated:
// 点击了NavigationController上的按钮 - (void)gotoCart:(UIButton *)sender { [self dismissAllPopTipViews]; if (sender == self.currentPopTipViewTarget) { self.currentPopTipViewTarget = nil; } else { CGFloat height; [self.tableView reloadData]; height = self.tableView.contentSize.height; self.tableView.frame = CGRectMake(0, 0, 100, height); self.tableView.backgroundColor = [UIColor blackColor]; self.tableView.alwaysBounceVertical = YES; CMPopTipView *popView = [[CMPopTipView alloc] initWithCustomView:self.tableView]; popView.delegate = self; popView.cornerRadius = 5; popView.backgroundColor = [UIColor blackColor]; popView.textColor = [UIColor whiteColor]; // 0是Slide 1是pop 2是Fade但是有问题,用前两个就好了 popView.animation = arc4random() % 1; // 立体效果,默认是YES popView.has3DStyle = arc4random() % 1; // popView.dismissTapAnywhere = YES; // [popView autoDismissAnimated:YES atTimeInterval:5.0]; [popView presentPointingAtView:sender inView:self.view animated:YES]; // 如果是原生的UIBarButtonItem,那么就调用这个方法 // popView presentPointingAtBarButtonItem:<#(UIBarButtonItem *)#> animated:<#(BOOL)#> [self.visiblePopTipViews addObject:popView]; self.currentPopTipViewTarget = sender; } }
以上的主要方法差不多介绍完了,出来看效果
他默认的尖尖Point三角形底边和高度是相等的,这样的Point看起来就会比较矮小,各位
如果有兴趣跑起来Demo看看就一定会想改一下
来看看他的源码,这种View的显示肯定在drawRect:的方法里面完成的
只截图该方法里面的一部分代码,我们只要把他处理的X坐标修改就行了
CGRect bubbleRect = [self bubbleFrame]; CGContextRef c = UIGraphicsGetCurrentContext(); CGContextSetRGBStrokeColor(c, 0.0, 0.0, 0.0, 1.0); // black CGContextSetLineWidth(c, self.borderWidth); CGMutablePathRef bubblePath = CGPathCreateMutable(); if (_pointDirection == PointDirectionUp) { // 这里的原点是point的尖尖 CGPathMoveToPoint(bubblePath, NULL, _targetPoint.x+_sidePadding, _targetPoint.y); // 注意这里的X轴是默认给的_pointer的宽度,这个pointer是个正三角形,但是我们要个等腰的,所有X轴加上_pointer/2,Y轴加上_pointer,OK CGPathAddLineToPoint(bubblePath, NULL, _targetPoint.x+_sidePadding+_pointerSize/2, _targetPoint.y+_pointerSize); CGPathAddArcToPoint(bubblePath, NULL, bubbleRect.origin.x+bubbleRect.size.width, bubbleRect.origin.y, bubbleRect.origin.x+bubbleRect.size.width, bubbleRect.origin.y+_cornerRadius, _cornerRadius); CGPathAddArcToPoint(bubblePath, NULL, bubbleRect.origin.x+bubbleRect.size.width, bubbleRect.origin.y+bubbleRect.size.height, bubbleRect.origin.x+bubbleRect.size.width-_cornerRadius, bubbleRect.origin.y+bubbleRect.size.height, _cornerRadius); CGPathAddArcToPoint(bubblePath, NULL, bubbleRect.origin.x, bubbleRect.origin.y+bubbleRect.size.height, bubbleRect.origin.x, bubbleRect.origin.y+bubbleRect.size.height-_cornerRadius, _cornerRadius); CGPathAddArcToPoint(bubblePath, NULL, bubbleRect.origin.x, bubbleRect.origin.y, bubbleRect.origin.x+_cornerRadius, bubbleRect.origin.y, _cornerRadius); // 这里也要改掉,不然自动关闭的时候就不是等腰三角形了 CGPathAddLineToPoint(bubblePath, NULL, _targetPoint.x+_sidePadding-_pointerSize/2, _targetPoint.y+_pointerSize); } else { // 上面改了那么下面也要改掉 CGPathMoveToPoint(bubblePath, NULL, _targetPoint.x+_sidePadding, _targetPoint.y); CGPathAddLineToPoint(bubblePath, NULL, _targetPoint.x+_sidePadding-_pointerSize/2, _targetPoint.y-_pointerSize); CGPathAddArcToPoint(bubblePath, NULL, bubbleRect.origin.x, bubbleRect.origin.y+bubbleRect.size.height, bubbleRect.origin.x, bubbleRect.origin.y+bubbleRect.size.height-_cornerRadius, _cornerRadius); CGPathAddArcToPoint(bubblePath, NULL, bubbleRect.origin.x, bubbleRect.origin.y, bubbleRect.origin.x+_cornerRadius, bubbleRect.origin.y, _cornerRadius); CGPathAddArcToPoint(bubblePath, NULL, bubbleRect.origin.x+bubbleRect.size.width, bubbleRect.origin.y, bubbleRect.origin.x+bubbleRect.size.width, bubbleRect.origin.y+_cornerRadius, _cornerRadius); CGPathAddArcToPoint(bubblePath, NULL, bubbleRect.origin.x+bubbleRect.size.width, bubbleRect.origin.y+bubbleRect.size.height, bubbleRect.origin.x+bubbleRect.size.width-_cornerRadius, bubbleRect.origin.y+bubbleRect.size.height, _cornerRadius); CGPathAddLineToPoint(bubblePath, NULL, _targetPoint.x+_sidePadding+_pointerSize/2, _targetPoint.y-_pointerSize); } CGPathCloseSubpath(bubblePath); CGContextSaveGState(c); CGContextAddPath(c, bubblePath); CGContextClip(c);
效果如下:
本次Demo地址:https://github.com/DeftMKJ/Pop 需要的小伙伴自行去尝试新的弹窗
貌似下载不了,说什么文件名太长了,反正不懂为什么,需要的同学可以像我拿或者直接
打开你的终端按以下操作clone一下
trainingvdi:~ MKJ$ cd ~/Desktop
trainingvdi:Desktop MKJ$ pwd
/Users/MKJ/Desktop
trainingvdi:Desktop MKJ$ mkdir hehe
trainingvdi:Desktop MKJ$ cd hehe/
trainingvdi:hehe MKJ$ pwd
/Users/MKJ/Desktop/hehe
trainingvdi:hehe MKJ$ git clone https://github.com/DeftMKJ/Pop.git
Cloning into ‘Pop‘...
remote: Counting objects: 361, done.
remote: Total 361 (delta 0), reused 0 (delta 0), pack-reused 361
Receiving objects: 100% (361/361), 407.47 KiB | 119.00 KiB/s, done.
Resolving deltas: 100% (142/142), done.
Checking connectivity... done.
然后打开你桌面的hehe文件夹就好了
OVER~~~~~~