自定义PopView

改代码是参考一个Demo直接改的,代码中有一些漏洞,如果发现其他的问题,可以下方直接留言

.h文件

#import <UIKit/UIKit.h>
typedef void(^PopoverBlock)(NSInteger index);
@interface CustomPopView : UIView
//@property(nonatomic,copy)void(^block)(int index);
//-(void)setDataArr:(NSArray *)titleArr withView:(id *)view withBlock:(void(^)(NSString *a))block;
@property (nonatomic, copy) NSArray *menuTitles;
@property(nonatomic,copy)void(^PopoverHiddenBlock)(BOOL isHidden );
- (void)showFromView:(id)aView selected:(PopoverBlock)selected;
@end@interface PopoverArrow : UIView@end

 .m文件

#import "CustomPopView.h"
// 字体大小
#define kPopoverFontSize 14.f// 十六进制颜色
#define UIColorFromRGB(rgbValue) [UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 green:((float)((rgbValue & 0xFF00) >> 8))/255.0 blue:((float)(rgbValue & 0xFF))/255.0 alpha:1.0]#define SCREEN_W [UIScreen mainScreen].bounds.size.width
#define SCREEN_H [UIScreen mainScreen].bounds.size.height// 箭头高度
#define kArrowH 8
// 箭头宽度
#define kArrowW 15
//每行的高度
#define CELL_HEIGHT 38
//
#define Identifier @"cell"// 边框颜色
#define kBorderColor UIColorFromRGB(0xE1E2E3)
@interface CustomPopView () <UITableViewDelegate, UITableViewDataSource>
{PopoverBlock _selectedBlock;UIView *_backgroundView;PopoverArrow *_arrowView;
}@property (nonatomic, retain) UITableView *tableView;@end@implementation CustomPopView
- (instancetype)initWithFrame:(CGRect)frame
{if (!(self = [super initWithFrame:frame])) return nil;self.backgroundColor = [UIColor clearColor];// 箭头_arrowView = [PopoverArrow new];[self addSubview:_arrowView];// tableView放在箭头底下, 用于箭头挡住tableView边框[self insertSubview:self.tableView belowSubview:_arrowView];return self;
}- (void)layoutSubviews
{[super layoutSubviews];// 设置tableView默认的分割线起终点位置if ([self.tableView respondsToSelector:@selector(setSeparatorInset:)]) {[self.tableView setSeparatorInset:UIEdgeInsetsZero];}if ([self.tableView respondsToSelector:@selector(setLayoutMargins:)]) {[self.tableView setLayoutMargins:UIEdgeInsetsZero];}self.tableView.layer.cornerRadius  = 5.f;self.tableView.layer.borderColor   = kBorderColor.CGColor;self.tableView.layer.borderWidth   = 1.f;
}#pragma mark -- getter- (UITableView *)tableView
{if (_tableView) return _tableView;_tableView = [UITableView new];_tableView.delegate        = self;_tableView.dataSource      = self;_tableView.rowHeight       = CELL_HEIGHT;_tableView.backgroundColor = [UIColor whiteColor];_tableView.showsVerticalScrollIndicator = NO;[_tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:Identifier];_tableView.tableFooterView = UIView.new;return _tableView;
}#pragma mark -- delegate- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{return self.menuTitles.count;
}- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:Identifier];cell.textLabel.font   = [UIFont systemFontOfSize:kPopoverFontSize];cell.textLabel.text   = [self.menuTitles objectAtIndex:indexPath.row];return cell;
}- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{if ([cell respondsToSelector:@selector(setSeparatorInset:)]) {[cell setSeparatorInset:UIEdgeInsetsZero];}if ([cell respondsToSelector:@selector(setLayoutMargins:)]) {[cell setLayoutMargins:UIEdgeInsetsZero];}
}- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{[UIView animateWithDuration:0.25 animations:^{self.alpha = 0;} completion:^(BOOL finished) {[_backgroundView removeFromSuperview];_backgroundView = nil;if (_selectedBlock) {_selectedBlock(indexPath.row);}[self removeFromSuperview];}];
}#pragma mark -- private
// 点击透明层隐藏
- (void)hide
{[UIView animateWithDuration:0.25 animations:^{self.alpha = 0;} completion:^(BOOL finished) {[_backgroundView removeFromSuperview];_backgroundView = nil;if(self.PopoverHiddenBlock){self.PopoverHiddenBlock(YES);}[self removeFromSuperview];}];
}#pragma mark -- public/*!*  @author lifution**  @brief 显示弹窗**  @param aView    箭头指向的控件*  @param selected 选择完成回调*/
- (void)showFromView:(id)aView selected:(PopoverBlock)selected
{if (selected) _selectedBlock = selected;//aView只能传两种参数,一种是UIView 另一种UIBarButtonItemif(!([aView isKindOfClass:[UIView class]] || [aView isKindOfClass:[UIBarButtonItem class]])){return;}UIWindow *keyWindow = [UIApplication sharedApplication].keyWindow;// 背景遮挡_backgroundView = UIView.new;_backgroundView.frame = keyWindow.bounds;_backgroundView.backgroundColor = [UIColor blackColor];_backgroundView.alpha = 0.2;_backgroundView.userInteractionEnabled = YES;[_backgroundView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hide)]];[keyWindow addSubview:_backgroundView];// 刷新数据更新contentSize[self.tableView reloadData];// 获取触发弹窗的按钮在window中的坐标CGRect triggerRect ;if([aView isKindOfClass:[UIView class]]){UIView *view = (UIView *)aView;triggerRect = [view convertRect:view.bounds toView:keyWindow];}else{UIView *bgView = [aView valueForKey:@"_view"];triggerRect = [bgView convertRect:bgView.bounds toView: keyWindow];}// 箭头指向的中心点CGFloat arrowCenterX = CGRectGetMaxX(triggerRect)-CGRectGetWidth(triggerRect)/2;// 取得标题中的最大宽度CGFloat maxWidth = 0;for (id obj in self.menuTitles) {if ([obj isKindOfClass:[NSString class]]) {CGSize titleSize = [obj sizeWithAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:kPopoverFontSize]}];if (titleSize.width > maxWidth) {maxWidth = titleSize.width;}}}CGFloat curWidth  = ((maxWidth+80)>SCREEN_W-30)?SCREEN_W-30:(maxWidth+80);CGFloat curHeight = CELL_HEIGHT*self.menuTitles.count+kArrowH;CGFloat curX      = arrowCenterX-curWidth/2;CGFloat curY      = CGRectGetMaxY(triggerRect)+10;// 如果箭头指向点距离屏幕右边减去5px不足curWidth的一半的话就重新设置curXif ((SCREEN_W-arrowCenterX-5)<curWidth/2) {curX = curX-(curWidth/2-(SCREEN_W-arrowCenterX-5));}// 如果箭头指向点距离屏幕左边加上5px不足curWidth的一半的话就重新设置curXif (arrowCenterX+5<curWidth/2) {curX = curX+(curWidth/2-arrowCenterX)+5;}//如果高度大于10行,则最高按10计算if(curHeight>CELL_HEIGHT*10+kArrowH){curHeight = CELL_HEIGHT*10+kArrowH;}self.frame           = CGRectMake(curX, curY - 18, curWidth, curHeight);_arrowView.frame     = CGRectMake(arrowCenterX-curX-kArrowW/2, 0, kArrowW, kArrowH+1);// 箭头高度 +1 遮挡住tableView的边框self.tableView.frame = CGRectMake(0, kArrowH, curWidth,curHeight - kArrowH );[keyWindow addSubview:self];self.alpha = 0;[UIView animateWithDuration:0.3 animations:^{self.alpha = 1;}];
}@end// 箭头
@implementation PopoverArrow- (instancetype)initWithFrame:(CGRect)frame
{if (!(self = [super initWithFrame:frame])) return nil;self.backgroundColor = [UIColor clearColor];return self;
}// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {[super drawRect:rect];// Drawing codeCGSize curSize = rect.size;CGContextRef context = UIGraphicsGetCurrentContext();CGContextSetLineWidth(context, 1);CGContextSetStrokeColorWithColor(context, kBorderColor.CGColor);CGContextSetFillColorWithColor(context, UIColor.whiteColor.CGColor);CGContextBeginPath(context);CGContextMoveToPoint(context, 0, curSize.height);CGContextAddLineToPoint(context, curSize.width/2, 0);CGContextAddLineToPoint(context, curSize.width, curSize.height);CGContextDrawPath(context, kCGPathFillStroke);
}@end

 使用:

view = [CustomPopView new];
view.menuTitles = @[@"1",@"2",@"3"]; 
UIBarButtonItem *item = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(addBtnClick:)];
self.navigationItem.rightBarButtonItem = item;-(void)addBtnClick:(UIBarButtonItem *)item{[view showFromView:item selected:^(NSInteger index) {}];
}

 

 

转载于:https://www.cnblogs.com/hualuoshuijia/p/9983821.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/387956.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

当编程语言掌握在企业手中,是生机还是危机?

2019年4月&#xff0c;Java的收费时代来临了&#xff01; Java是由Sun微系统公司在1995年推出的编程语言&#xff0c;2010年Oracle收购了Sun之后&#xff0c;Java的所有者也就自然变成了Oracle。2019年&#xff0c;Oracle宣布将停止Java 8更新的免费支持&#xff0c;未来Java的…

数据可视化 信息可视化_动机可视化

数据可视化 信息可视化John Snow’s map of Cholera cases near London’s Broad Street.约翰斯诺(John Snow)在伦敦宽街附近的霍乱病例地图。 John Snow, “the father of epidemiology,” is famous for his cholera maps. These maps represent so many of our aspirations …

android 接听和挂断实现方式

转载▼标签&#xff1a; android 接听 挂断 it 分类&#xff1a; android应用技巧 参考&#xff1a;android 来电接听和挂断 支持目前所有版本 注意&#xff1a;android2.3版本及以上不支持下面的自动接听方法。 &#xff08;会抛异常&#xff1a;java.lang.Securi…

利用延迟关联或者子查询优化超多分页场景

2019独角兽企业重金招聘Python工程师标准>>> MySQL并不是跳过offset行&#xff0c;而是取offsetN行&#xff0c;然后返回放弃前offset行&#xff0c;返回N行&#xff0c;那当offset 特别大的时候&#xff0c;效率就非常的低下&#xff0c;要么控制返回的总页数&…

客户流失_了解客户流失

客户流失Big Data Analytics within a real-life example of digital music service数字音乐服务真实示例中的大数据分析 Customer churn is a key predictor of the long term success or failure of a business. It is the rate at which customers are leaving your busine…

Nginx:Nginx limit_req limit_conn限速

简介 Nginx是一个异步框架的Web服务器&#xff0c;也可以用作反向代理&#xff0c;负载均衡器和HTTP缓存&#xff0c;最常用的便是Web服务器。nginx对于预防一些攻击也是很有效的&#xff0c;例如CC攻击&#xff0c;爬虫&#xff0c;本文将介绍限制这些攻击的方法&#xff0c;可…

Linux实战教学笔记12:linux三剑客之sed命令精讲

第十二节 linux三剑客之sed命令精讲 标签&#xff08;空格分隔&#xff09;&#xff1a; Linux实战教学笔记-陈思齐 ---更多资料点我查看 1&#xff0c;前言 我们都知道&#xff0c;在Linux中一切皆文件&#xff0c;比如配置文件&#xff0c;日志文件&#xff0c;启动文件等等。…

activiti 为什么需要采用乐观锁?

乐观锁 为什么需要采用乐观锁&#xff1f; 由于activiti一个周期的transaction时间可能比较长&#xff0c;且同一流程实例中存在任务并发执行等场景。设计者将update、insert、delete事务性的操作推迟至command结束时完成&#xff0c;这样尽量降低锁冲突的概率&#xff0c;由…

支付宝架构

支付宝系统架构图如下&#xff1a; 支付宝架构文档有两个搞支付平台设计的人必须仔细揣摩的要点。 一个是账务处理。在记账方面&#xff0c;涉及到内外两个子系统&#xff0c;外部子系统是单边账&#xff0c;满足线上性能需求&#xff1b;内部子系统走复式记账&#xff0c;满足…

Android Studio 导入新工程项目

1 导入之前先修改工程下相关文件 1.1 只需修改如下三个地方1.2 修改build.gradle文件 1.3 修改gradle/wrapper/gradle-wrapper.properties 1.4 修改app/build.gradle 2 导入修改后的工程 2.1 选择File|New|Import Project 2.2 选择修改后的工程 如果工程没有变成AS符号&#xf…

马蜂窝张矗:绩效考核是为了激发工作潜力,而不是逃避问题

3 月 23 日&#xff0c;由高端技术领导者社交平台 TGO 鲲鹏会主办的 GTLC 全球技术领导峰会分站首站在北京举行。会上马蜂窝技术副总裁 \u0026amp; TGO 鲲鹏会会员张矗发表了主题为“我在马蜂窝的技术管理实践”的演讲。本文根据其演讲整理而成。大家好&#xff0c;我是来自马蜂…

fiddler抓包1-抓小程序https包

抓小程序包和抓app包是一样的操作方法&#xff1b;安卓用fiddler&#xff0c;ios用charles&#xff1b; 一、环境准备 1.电脑已装最新版fiddler 2.手机和电脑在同一局域网 二、fiddler设置 1.fiddler>Tools>Options>HTTPS 勾选Capture HTTPS CONNECTs 及下边的子项&am…

冲刺第七天

今天任务进行情况&#xff1a;今天我们将我们的游戏导到界面形成可用的应用程序&#xff0c;并且进行调试与运行&#xff0c;让同学试玩&#xff0c;发现了困难并加以改正。 遇到的困难及解决方法&#xff1a; 运行时发现游戏界面中UI的button和image的位置会随分辨率的不同而发…

Node.js Streams:你需要知道的一切

Node.js Streams&#xff1a;你需要知道的一切 图像来源 Node.js流以难以使用而闻名&#xff0c;甚至更难理解。好吧&#xff0c;我有个好消息 - 不再是这样了。 多年来&#xff0c;开发人员在那里创建了许多软件包&#xff0c;其唯一目的是简化流程。但在本文中&#xff0c;我…

shell之引号嵌套引号大全

万恶的引号 这个能看懂你就出师了! 转载于:https://www.cnblogs.com/theodoric008/p/10000480.html

oracle表分区详解

oracle表分区详解 从以下几个方面来整理关于分区表的概念及操作: 表空间及分区表的概念表分区的具体作用表分区的优缺点表分区的几种类型及操作方法对表分区的维护性操作 1.表空间及分区表的概念 表空间&#xff1a; 是一个或多个数据文件的集合&#xff0c;所有的数据对象都存…

如果您不将Docker用于数据科学项目,那么您将生活在1985年

重点 (Top highlight)One of the hardest problems that new programmers face is understanding the concept of an ‘environment’. An environment is what you could say, the system that you code within. In principal it sounds easy, but later on in your career yo…

jmeter对oracle压力测试

下载Oracle的jdbc数据库驱动包&#xff0c;注意Oracle数据库的版本&#xff0c;这里使用的是&#xff1a;Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production&#xff1b; 一般数据库的驱动包文件在安装路径下&#xff1a;D:\oracle\product\10.2.…

docker部署flask_使用Docker,GCP Cloud Run和Flask部署Scikit-Learn NLP模型

docker部署flaskA brief guide to building an app to serve a natural language processing model, containerizing it and deploying it.构建用于服务自然语言处理模型&#xff0c;将其容器化和部署的应用程序的简要指南。 By: Edward Krueger and Douglas Franklin.作者&am…

SQL的执行计划

SQL的执行计划实际代表了目标SQL在Oracle数据库内部的具体执行步骤&#xff0c;作为调优&#xff0c;只有知道了优化器选择的执行计划是否为当前情形下最优的执行计划&#xff0c;才能够知道下一步往什么方向。 执行计划的定义&#xff1a;执行目标SQL的所有步骤的组合。 我们首…