您的位置:首页 > 产品设计 > UI/UE

UI总结之cell之手势滑动

2015-09-28 20:39 531 查看
// 1. UIViewController
#import "ViewController.h"
#import "CustomCell.h"

@interface ViewController () <UITableViewDataSource,UITableViewDelegate>

@property (weak, nonatomic) IBOutlet UITableView *tableView;

@property (nonatomic, strong) NSMutableArray *dataSourceArray;

@end

@implementation ViewController

- (NSMutableArray *)dataSourceArray {

if (_dataSourceArray == nil) {
_dataSourceArray = [[NSMutableArray alloc] init];
for (int i = 0; i < 20; i++) {
[_dataSourceArray addObject:[NSString stringWithFormat:@"name-%d",i+1]];
}
}
return _dataSourceArray;
}

- (void)viewDidLoad {

[super viewDidLoad];

// 注册cell
NSString *className = NSStringFromClass([CustomCell class]);
[self.tableView registerClass:[CustomCell class] forCellReuseIdentifier:className];
// 设置cell的高度  这样直接设置会比起使用代理方法设置cell高度提高性能
self.tableView.rowHeight = 80.0f;
}

#pragma mark -
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

return [self.dataSourceArray count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

NSString *className = NSStringFromClass([CustomCell class]);
CustomCell *cell =  [tableView dequeueReusableCellWithIdentifier:className forIndexPath:indexPath];
cell.name = [self.dataSourceArray objectAtIndex:indexPath.row];
// 取消选中样式
cell.selectionStyle = UITableViewCellSelectionStyleNone;

// 设置按钮
[cell setActionButtonWithTitle:@"设置" direction:ActionButtonDirectionLeft actionButtonBlock:^(CustomCell *cell) {
NSLog(@"设置");
}];

[cell setActionButtonWithTitle:@"删除" direction:ActionButtonDirectionRight actionButtonBlock:^(CustomCell *cell) {
// 0. 根据cell获取当前的indexPath
NSIndexPath *currentIndexPath = [tableView indexPathForCell:cell];
// 1. 删除数据源
[self.dataSourceArray removeObjectAtIndex:currentIndexPath.row];
// 2. 删除cell
[tableView deleteRowsAtIndexPaths:@[currentIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic];

}];

// 这个块 是为了只让当前的cell显示 删除和设置按钮
[cell setBeginPanGestureActionBlock:^(CustomCell *cell){
// 当前屏幕上可以看到的cell
NSIndexPath *indexPath_cell = [tableView indexPathForCell:cell];
for (CustomCell *visibleCell in [tableView visibleCells]) {

NSIndexPath *indexPath_c = [tableView indexPathForCell:visibleCell];
// 判断cell的位置 需要判断section和row
if (indexPath_c.section == indexPath_cell.section && indexPath_c.row == indexPath_cell.row) {
// 不刷新
} else {
// 刷新
[tableView reloadRowsAtIndexPaths:@[indexPath_c] withRowAnimation:UITableViewRowAnimationNone];
}
}

}];
return cell;
}

// 2. CustomCell.h
#import <UIKit/UIKit.h>

// button的位置
typedef NS_ENUM(NSInteger, ActionButtonDirection) {
/** 左边 */
ActionButtonDirectionLeft,
/** 右边 */
ActionButtonDirectionRight,
} ;

@class CustomCell;
// 按钮点击回调
typedef void(^ActionButtonBlock)(CustomCell *cell);
// 开始拖动回调
typedef void(^BeginPanGestureActionBlock)(CustomCell *cell);

@interface CustomCell : UITableViewCell

/** cell的内容  */
@property (nonatomic,copy) NSString *name;

/**
*  设置按钮属性和回调事件等
*
*  @param title             按钮的标题
*  @param direction         按钮的位置 是在左还是在右
*  @param actionButtonBlock 按钮点击事件block回调
*/
- (void)setActionButtonWithTitle:(NSString *)title direction:(ActionButtonDirection)direction actionButtonBlock:(ActionButtonBlock)actionButtonBlock;

/**
*  设置开始拖动的回调
*/
- (void)setBeginPanGestureActionBlock:(BeginPanGestureActionBlock)beginPanGestureActionBlock;

// CustomCell.m
#import "CustomCell.h"

/** 按钮的个数 */
#define kNumbersOfActionButton 2
/** 按钮高度 */
#define kActionButtonHeight self.contentView.frame.size.height
/** 按钮宽度 */
#define kActionButtonWidth  120
/** 左边按钮tag */
#define kActionLeftButtonTag 2
/** 右边按钮tag */
#define kActionRightButtonTag 1

#define kAnimatedDuration 0.3f

@interface CustomCell () <UIGestureRecognizerDelegate>

/** 内容视图 */
@property (nonatomic, weak) UIView *cellContentView;

@property (nonatomic, weak) UILabel *nameLabel;

/** 删除按钮的block回调 */
@property (nonatomic, copy) ActionButtonBlock actionRightButtonBlock;
/** 设置按钮的block回调 */
@property (nonatomic, copy) ActionButtonBlock actionLeftButtonBlock;
/** 手势开始状态的block回调 */
@property (nonatomic, copy) BeginPanGestureActionBlock beginPanGestureActionBlock;

@end

@implementation CustomCell

#pragma mark - 初始化操作

- (void)initViews {

[self createActionButton];

[self addPanGestToCellContentView];
}

// 创建cell的时候会走到这个方法 会调用这个方法屏幕 ‘cell数量+1’ 次
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {

self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
[self initViews];
}
return self;
}

/**
* 与 awakeFromNib 的区别  xib里面的子控件还没有创建出来
* 只用来初始化自身
*/
- (id)initWithCoder:(NSCoder *)aDecoder {

self = [super initWithCoder:aDecoder];
if (self) {
[self initViews];
}
return self;
}

/**
* 与 initWithCoder: 的区别  xib里面的子控件全都创建出来了
* 用来初始化子控件们
*/
- (void)awakeFromNib {

}

#pragma mark - 懒加载

- (UIView *)cellContentView {

if (_cellContentView == nil) {
UIView *cellContentView = [[UIView alloc] init];
cellContentView.backgroundColor = [UIColor whiteColor];
[self.contentView addSubview:cellContentView];
_cellContentView = cellContentView;
}
return _cellContentView;
}

- (UILabel *)nameLabel {

if (_nameLabel == nil) {
UILabel *nameLabel = [[UILabel alloc] init];
[self.cellContentView addSubview:nameLabel];
nameLabel.backgroundColor = [UIColor orangeColor];
_nameLabel = nameLabel;
}
return _nameLabel;
}

#pragma mark - layout

- (void)layoutSubviews {

self.cellContentView.frame = self.contentView.bounds;
self.nameLabel.frame = self.contentView.bounds;
// 设置按钮的大小
for (int i = 0; i < kNumbersOfActionButton; i++) {
UIButton *btn = (UIButton *)[self.contentView viewWithTag:i+1];
btn.frame = CGRectMake(self.frame.size.width-(i+1) *kActionButtonWidth, 0, kActionButtonWidth, kActionButtonHeight);
}
[super layoutSubviews];
}

#pragma mark - GestureRecognizer

- (void)addPanGestToCellContentView {

UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGestAction:)];
// 设置代理
pan.delegate = self;
[self.cellContentView addGestureRecognizer:pan];
}

- (void)panGestAction:(UIPanGestureRecognizer *)panGest {

// 根据状态设置东西 当开始滑动手势的时候,需要刷新其余cell,只让当前cell 显示设置和删除按钮
if (panGest.state == UIGestureRecognizerStateBegan) { // 手势开始

if (_beginPanGestureActionBlock) {
_beginPanGestureActionBlock(self);
}

} else if (panGest.state == UIGestureRecognizerStateChanged) { // 手势移动

CGPoint point = [panGest translationInView:self.contentView];

// 修改中心点坐标
CGFloat centerX = self.cellContentView.center.x + point.x;

// 情况1. 刚开始 直接右滑
if (centerX > self.contentView.center.x) {
centerX = self.contentView.center.x;
self.cellContentView.center = CGPointMake(centerX, self.cellContentView.center.y);
}

// 情况2. 按钮显示  右滑
if ((point.x > 0 && self.cellContentView.center.x < self.contentView.center.x)) {
self.cellContentView.center = CGPointMake(centerX, self.cellContentView.center.y);
}

// 情况3. 删除按钮显示不完全,回弹
if (centerX < self.contentView.center.x && centerX > self.contentView.center.x - kActionButtonWidth) {
self.cellContentView.center = CGPointMake(centerX, self.cellContentView.center.y);
}

// 情况4. 删除按钮显示完全
if (centerX < self.contentView.center.x-kActionButtonWidth && centerX > self.contentView.center.x-kActionButtonWidth*kNumbersOfActionButton) {
self.cellContentView.center = CGPointMake(centerX, self.cellContentView.center.y);
}

// translation需要归0因为是不断增加的。
[panGest setTranslation:CGPointZero inView:self.cellContentView];

} else if (panGest.state == UIGestureRecognizerStateEnded) { // 手势结束

if (self.cellContentView.center.x > self.contentView.center.x - kActionButtonWidth && self.cellContentView.center.x < self.contentView.center.x) {

[UIView animateWithDuration:kAnimatedDuration animations:^{

self.cellContentView.center = CGPointMake(self.contentView.center.x, self.cellContentView.center.y);
}];
}
if ((self.cellContentView.center.x < (self.contentView.center.x-kActionButtonWidth)) && (self.cellContentView.center.x > (self.contentView.center.x-kActionButtonWidth*kNumbersOfActionButton))) {

[UIView animateWithDuration:kAnimatedDuration animations:^{

self.cellContentView.center = CGPointMake(self.contentView.center.x-kActionButtonWidth*kNumbersOfActionButton, self.cellContentView.center.y);
}];
}

b719

}
}

#pragma mark - 按钮

- (void)setActionButtonWithTitle:(NSString *)title
direction:(ActionButtonDirection)direction
actionButtonBlock:(ActionButtonBlock)actionButtonBlock {

NSInteger tag = kActionLeftButtonTag;

// 如果是右按钮
if (direction == ActionButtonDirectionRight) {
tag = kActionRightButtonTag;
_actionRightButtonBlock = actionButtonBlock;
} else {
_actionLeftButtonBlock = actionButtonBlock;
}
UIButton *btn = (UIButton *)[self.contentView viewWithTag:tag];
[btn setTitle:title forState:UIControlStateNormal];
}

- (void)setBeginPanGestureActionBlock:(BeginPanGestureActionBlock)beginPanGestureActionBlock {

_beginPanGestureActionBlock = beginPanGestureActionBlock;
}

- (void)createActionButton {

for (int i = 0; i < kNumbersOfActionButton; i++) {
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
[self.contentView addSubview:btn];
if (i == 0) {   // 如果是右边按钮
btn.backgroundColor = [UIColor redColor];
btn.tag = kActionRightButtonTag;
} else {        // 如果是左边按钮
btn.backgroundColor = [UIColor lightGrayColor];
btn.tag = kActionLeftButtonTag;
}
[btn addTarget:self action:@selector(btnAction:) forControlEvents:UIControlEventTouchUpInside];
}
}

- (void)btnAction:(UIButton *)btn {

if (btn.tag == kActionLeftButtonTag && _actionLeftButtonBlock) {
_actionLeftButtonBlock(self);
}
if (btn.tag == kActionRightButtonTag && _actionRightButtonBlock) {
_actionRightButtonBlock(self);
}

}

#pragma mark - setter

- (void)setName:(NSString *)name {

_name = [name copy];
self.nameLabel.text = _name;
}

#pragma mark - 手势代理方法

/**
*  通过此代理方法实现 上下拖动和左右拖动的区分
*  如果 左右拖动幅度  大于 上下拖动幅度
*/
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {

if ([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]) {

UIPanGestureRecognizer *pan = (UIPanGestureRecognizer *)gestureRecognizer;
CGPoint point = [pan translationInView:self.contentView];
// 左右滑动
if (fabs(point.x) > fabs(point.y)) {
return YES;
}
}

return NO;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: