iOS 可高度自定义的底部弹框
技术: iOS Objective-C
概述
一个可以让开发者通过编写 tableView 的内容随心所欲的定制自己想要的底部弹框
详细
一. 运行效果图
二. 实现过程
1. 实现一个有遮罩效果的半透明 view,然后添加一个可设置展示内容高度的 contentView
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | // 这个遮罩是可以遮住全屏 - ( void )createUI{ self.frame = CGRectMake( 0 , 0 , SS_ScreenW, SS_ScreenH); self.backgroundColor = [UIColor colorWithRed: 0 green: 0 blue: 0 alpha: 0.4 ]; self.userInteractionEnabled = YES; [self addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(disMissView)]]; [self.contentView addSubview:self.tbView]; } // contentView 是通过懒加载实现的 - (UIView *)contentView{ if (!_contentView) { _contentView = [UIView new ]; _contentView.backgroundColor = [UIColor whiteColor]; _contentView.frame = CGRectMake( 0 , SS_ScreenH - _contentHeight - SS_BottomMargin, SS_ScreenW, _contentHeight + SS_BottomMargin); _contentView.opaque = YES; [self addSubview:_contentView]; } return _contentView; } |
2. 我们实现的底部弹框实质上一个可滑动的表单(tableView),在 contentView 上添加一个 tableView
1 2 3 4 5 6 7 8 9 10 | - (UITableView *)tbView{ if (!_tbView) { // _tbView = [[UITableView alloc]initWithFrame:CGRectZero style:UITableViewStyleGrouped]; _tbView = [UITableView new ]; _tbView.delegate = self; _tbView.dataSource = self; [_tbView registerClass:[UITableViewCell class ] forCellReuseIdentifier:@ "ss" ]; } return _tbView; } |
3. 通过设置UIView 动画,实现遮罩 menuView 的展示和消失效果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | // 将 menuView 展示在父 view 上 [view addSubview:self]; [view addSubview:self.contentView]; self.contentView.frame = CGRectMake( 0 , SS_ScreenH, SS_ScreenW, _contentHeight); __weak typeof (self) weakSelf = self; [UIView animateWithDuration:_animationDuration animations:^{ self.alpha = 1.0 ; self.contentView.frame = CGRectMake( 0 , SS_ScreenH - weakSelf.contentHeight - SS_BottomMargin, SS_ScreenW, weakSelf.contentHeight + SS_BottomMargin); } completion:^(BOOL finished) { }]; // 将 menuView 从父 view 上移除 __weak typeof (self) weakSelf = self; [UIView animateWithDuration:_animationDuration animations:^{ self.alpha = 0.0 ; self.contentView.frame = CGRectMake( 0 , SS_ScreenH, SS_ScreenW, weakSelf.contentHeight); } completion:^(BOOL finished) { [self removeFromSuperview]; [self.contentView removeFromSuperview]; }]; |
4. 实现选项和头部的定制化
通过编写自己的代理方法,让开发人员根据自己项目的实际需要设置各个选项,并且可以定制固定的头部以及底部
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | @protocol SSMenuViewDelegate <NSObject> @required; // 返回 tableView 的行数 - (NSInteger)menuTableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section; // 返回 tableViewCell 需要自定义 cell 的分割线 - (UITableViewCell *)menuTableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath; @optional; // 设置组数 - (NSInteger)menuNumberOfSectionsInTableView:(UITableView *)tableView; // 选中某个 tableView Cell - ( void )menuTableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath; // 定义每个选项的cell的高度 - (CGFloat)menuTableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath; // 定义headerView - (UIView *)menuTableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section; // 定义headerView 的高度 - (CGFloat)menuTableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section; // 定义 footterView - (UIView *)menuTableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section; - (CGFloat)menuTableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section; @end |
三. 项目结构
四. 使用手册
1. 首先,根据目录,将 SSMenuView.h, SSMenuView.m 文件,添加到自己项目中
2. 创建弹框控件
由于在使用类似弹框的时候,用户可能会多次点击使用,为了避免重复创建,建议使用懒加载创建一个弹窗控件
1 2 3 4 5 6 7 8 9 10 11 | # pragma # pragma mark - Lazy - - (SSMenuView *)menuView{ if (!_menuView) { _menuView = [SSMenuView new ]; _menuView.delegate = self; // _menuView.contentHeight = 44 * 6; // _menuView.tbView.separatorStyle = UITableViewCellSeparatorStyleNone; } return _menuView; } |
3. 根据自己的项目需要,创建自己的弹框内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | # pragma # pragma mark - SSMenuViewDelegate - - (NSInteger)menuTableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ return 4 ; } - (UITableViewCell *)menuTableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@ "cellID" ]; if (!cell) { cell = [[UITableViewCell alloc]initWithStyle:(UITableViewCellStyleDefault) reuseIdentifier:@ "cellID" ]; } cell.textLabel.textAlignment = NSTextAlignmentCenter; cell.textLabel.text = [NSString stringWithFormat:@ "这是选项%ld" ,indexPath.row]; cell.selectionStyle = UITableViewCellSelectionStyleNone; return cell; } - (CGFloat)menuTableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section{ return 44 ; } - (CGFloat)menuTableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{ return 44 ; } - (UIView *)menuTableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section{ UIView *footer = [UIView new ]; footer.backgroundColor = [UIColor orangeColor]; return footer; } - (UIView *)menuTableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{ UIView *header = [UIView new ]; header.backgroundColor = [UIColor whiteColor]; header.frame = CGRectMake( 0 , 0 , [UIScreen mainScreen].bounds.size.width, 44 ); UILabel *lab = [UILabel new ]; lab.text = @ "这是选项的头部" ; [header addSubview:lab]; lab.textAlignment = NSTextAlignmentCenter; lab.frame = header.frame; return header; } |
4. 根据需要,在触发点击事件,弹出弹框
此处,有2种展示方式,根据开发者自己的需要选择是否将弹框完全全屏
1 2 3 4 5 6 | - (IBAction)click:(id)sender { // [self.menuView showInView:self.view]; [self.menuView showInWindow]; } // 隐藏弹框 [self.menuView disMissView]; |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
· C++代码改造为UTF-8编码问题的总结
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库