待实现需求:在Cell中点击Button实现弹窗效果,点击弹窗中的Button实现Cell的数据源删除。
设计弹窗
首先我们需要设计一个弹窗视图,以一个简单的弹窗代码为例。
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface DeleteCellView : UIView
// 展示弹窗,实现弹窗内部Button点击方法
- (void)showDeleteViewFromPoint:(CGPoint)point clickBlock:(dispatch_block_t)block;
// 弹窗消失
- (void)dismissDeleteView;
@end
#import "DeleteCellView.h"
@interface DeleteCellView ()
@property(nonatomic, strong, readwrite) UIView *backGroundView; // 背景图
@property(nonatomic, strong, readwrite) UIButton *deleteButton; // 删除按钮
@property(nonatomic, copy, readwrite) dispatch_block_t block;// 实现闭包
@end
@implementation DeleteCellView
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
_backGroundView = [[UIView alloc] initWithFrame:self.bounds];
_backGroundView.backgroundColor = [UIColor blackColor];
_backGroundView.alpha = 0.4;
// 背景添加手势,实现点击弹窗消失
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissDeleteView)];
[_backGroundView addGestureRecognizer:tapGesture];
[self addSubview:_backGroundView];
_deleteButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];
_deleteButton.backgroundColor = [UIColor blueColor];
[_deleteButton addTarget:self action:@selector(clickButton) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:_deleteButton];
}
return self;
}
- (void)showDeleteViewFromPoint:(CGPoint)point clickBlock:(dispatch_block_t)block {
// 设置button的动画初始位置,
_deleteButton.frame = CGRectMake(point.x, point.y, 0, 0);
self.block = [block copy];
// 将弹窗加入到主窗口
[[[UIApplication sharedApplication].windows objectAtIndex:0] addSubview:self];
// 弹窗动画
[UIView animateWithDuration:1.f delay:0.f usingSpringWithDamping:0.5 initialSpringVelocity:0.5 options:UIViewAnimationOptionCurveEaseIn animations:^{
self.deleteButton.frame = CGRectMake((self.bounds.size.width - 200) / 2, (self.bounds.size.height - 200) / 2, 200, 200);
} completion:nil];
}
- (void)dismissDeleteView {
// 从父视图移除
[self removeFromSuperview];
}
- (void)clickButton{
// 点击按钮实现
if (_block) {
_block();
}
[self dismissDeleteView];
}
@end
逻辑实现
我们现在有了弹窗,那么如何实现点击cell中的button实现弹窗呢?首先看看我们实现弹窗需要什么参数?
我们只需要调用- (void)showDeleteViewFromPoint:(CGPoint)point clickBlock:(dispatch_block_t)block;
方法即可展示弹窗。
- point。弹窗从屏幕中哪个起点展示弹窗动画。
- block。弹窗中的按钮实现。
所以要处理弹窗的实现,我们只需要关注如何取到point参数的值。我们需要tableView和cell和相应的button属性,那么我们便在ViewController中处理比较方便。
方法1:代理处理。我们实现一个代理方法,参数为UITableViewCell和UIButton。在cell中添加代理属性,viewcontroller设置为cell的代理,实现代理方法。cell中的button调用代理方法。
方法2: 闭包处理。在cell中添加一个闭包属性,参数为UIButton,在cellForRowAtIndexPath
中实现闭包。我们有了button参数,cell属性,tableview属性便很容易实现弹窗方法。cell中的button调用闭包。
代理实现
添加代理
@protocol NormalTableViewCellDelegate <NSObject>
- (void)tableViewCell:(UITableViewCell *)tableViewCell clickDeleteButton:(UIButton *)deleteButton;
@end
@interface NormalTableViewCell : UITableViewCell
- (void)layoutTableViewCell;
@property (nonatomic, weak, readwrite) id<NormalTableViewCellDelegate> delegate;
@end
我们为cell添加一个代理方法来实现弹窗效果。点击button的触发去调用代理方法。
- (void)deleteButtonClick {
if (self.delegate && [self.delegate respondsToSelector:@selector(tableViewCell:clickDeleteButton:)]) {
[self.delegate tableViewCell:self clickDeleteButton:self.deleteButton];
}
}
实现代理
我们在Viewcontroller中实现代理方法,来实现弹窗的展示。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NormalTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"id"];
if (!cell) {
cell = [[NormalTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"id"];
}
// 设置代理
cell.delegate = self;
[cell layoutTableViewCell];
return cell;
}
- (void)tableViewCell:(UITableViewCell *)tableViewCell clickDeleteButton:(UIButton *)deleteButton {
DeleteCellView *deleteView = [[DeleteCellView alloc] initWithFrame:self.view.bounds];
// 坐标系转换
CGRect rect = [tableViewCell convertRect:deleteButton.frame toView:nil];
__weak typeof(self) weakSelf = self;
[deleteView showDeleteViewFromPoint:rect.origin clickBlock:^{
__strong typeof(weakSelf) strongSelf = weakSelf;
// 修改数据源
[strongSelf.dataArray removeObjectAtIndex:[self.tableView indexPathForCell:tableViewCell].row];
[strongSelf.tableView deleteRowsAtIndexPaths:@[[self.tableView indexPathForCell:tableViewCell]] withRowAnimation:UITableViewRowAnimationFade];
}];
}
闭包实现
为cell添加一个闭包属性,传入UIButton参数。
@property (nonatomic, copy, readwrite) void(^block)(UIButton *button);
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
CustomTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
if (!cell) {
cell = [[CustomTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"cell"];
}
__weak typeof(self) WeakSelf = self;
__weak typeof(cell) WeakCell = cell;
cell.block = ^(UIButton * _Nonnull button) {
__strong typeof(WeakSelf) StrongSelf = WeakSelf;
__strong typeof(WeakCell) StrongCell = WeakCell;
CGRect rect = [StrongCell convertRect:button.frame toView:nil];
DeleteView *deleteView = [[DeleteView alloc] initWithFrame:self.view.bounds];
[deleteView showDeleteViewFrom:rect.origin clickBlock:^{
[StrongSelf.array removeLastObject];
[StrongSelf.tableView deleteRowsAtIndexPaths:@[[StrongSelf.tableView indexPathForCell:StrongCell]] withRowAnimation:UITableViewRowAnimationFade];
}];
};
return cell;
}