iOS - 点击Cell内部Button弹窗实现

待实现需求:在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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值