Skip to content

Commit

Permalink
UI improved for cell deletion. Pass-thru scroll view delegate methods…
Browse files Browse the repository at this point in the history
… added.
  • Loading branch information
alekseyn committed Apr 28, 2017
1 parent f2379ab commit 77577a3
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 86 deletions.
16 changes: 12 additions & 4 deletions Classes/EasyTableView.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
scrolling direction of an EasyTableView, drags the cell out of the EasyTableView.
If touches end with the cell away from the EasyTableView it will be deleted.
Otherwise it will animate back to it's normal position. This feature is invoked by
returning YES to the easyTableViewAllowsCellDeletion: delegate method. If this
returning YES to the easyTableViewAllowsCellDeletion: delegate method. If this
feature is used, the easyTableView:didDeleteCellAtIndexPath: delegate method must
be implemented and must update the table view data store accordingly.
Expand All @@ -42,7 +42,7 @@
#import <UIKit/UIKit.h>

typedef NS_ENUM(NSUInteger, EasyTableViewOrientation) {
EasyTableViewOrientationVertical,
EasyTableViewOrientationVertical,
EasyTableViewOrientationHorizontal
};

Expand All @@ -53,14 +53,22 @@ typedef NS_ENUM(NSUInteger, EasyTableViewOrientation) {
- (UITableViewCell *)easyTableView:(EasyTableView *)easyTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
@optional
- (NSUInteger)numberOfSectionsInEasyTableView:(EasyTableView*)easyTableView;
- (void)easyTableView:(EasyTableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
- (void)easyTableView:(EasyTableView *)easyTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
- (UIView *)easyTableView:(EasyTableView*)easyTableView viewForHeaderInSection:(NSInteger)section;
- (UIView *)easyTableView:(EasyTableView*)easyTableView viewForFooterInSection:(NSInteger)section;
- (CGFloat)easyTableView:(EasyTableView *)easyTableView heightOrWidthForCellAtIndexPath:(NSIndexPath *)indexPath;

// Implement both of these methods for the cell deletion feature
// Implement the first two of these methods for the cell deletion feature
- (BOOL)easyTableViewAllowsCellDeletion:(EasyTableView *)easyTableView;
- (void)easyTableView:(EasyTableView *)easyTableView didDeleteCellAtIndexPath:(NSIndexPath *)indexPath;
- (void)easyTableViewHasPendingCellDeletion:(EasyTableView *)easyTableView;
- (void)easyTableView:(EasyTableView *)easyTableView cell:(UITableViewCell *)cell deletionIsEminent:(BOOL)eminent;

// ScrollViewDelegate pass-through methods
- (void)easyTableViewWillBeginDragging:(EasyTableView *)easyTableView;
- (void)easyTableViewDidEndDragging:(EasyTableView *)easyTableView willDecelerate:(BOOL)decelerate;
- (void)easyTableViewWillBeginDecelerating:(EasyTableView *)easyTableView;
- (void)easyTableViewDidEndDecelerating:(EasyTableView *)easyTableView;
@end


Expand Down
197 changes: 115 additions & 82 deletions Classes/EasyTableView.m
Original file line number Diff line number Diff line change
Expand Up @@ -19,62 +19,62 @@ @implementation EasyTableView {
#pragma mark - Initialization

- (id)initWithFrame:(CGRect)frame ofWidth:(CGFloat)width {
if (self = [super initWithFrame:frame]) {
if (self = [super initWithFrame:frame]) {
self.orientation = EasyTableViewOrientationHorizontal;
self.tableView = [UITableView new];
self.tableView.rowHeight = width;
self.tableView = [UITableView new];
self.tableView.rowHeight = width;
}
return self;
return self;
}


- (id)initWithFrame:(CGRect)frame ofHeight:(CGFloat)height {
if (self = [super initWithFrame:frame]) {
if (self = [super initWithFrame:frame]) {
self.orientation = EasyTableViewOrientationVertical;
self.tableView = [UITableView new];
self.tableView.rowHeight = height;
}
return self;
self.tableView = [UITableView new];
self.tableView.rowHeight = height;
}
return self;
}

#pragma mark - Properties

- (void)setTableView:(UITableView *)tableView {
_tableView = tableView;

self.orientation = _orientation;

_tableView.delegate = self;
_tableView.dataSource = self;
_tableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
_tableView = tableView;

self.orientation = _orientation;

[self addSubview:_tableView];
_tableView.delegate = self;
_tableView.dataSource = self;
_tableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

[self addSubview:_tableView];
}

- (void)setFrame:(CGRect)frame {
super.frame = frame;
self.orientation = _orientation;
super.frame = frame;
self.orientation = _orientation;
}

- (void)setOrientation:(EasyTableViewOrientation)orientation {
_orientation = orientation;
if (!self.tableView)
return;
self.tableView.transform = CGAffineTransformIdentity;
self.tableView.frame = CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height);
if (_orientation == EasyTableViewOrientationHorizontal) {
int xOrigin = (self.bounds.size.width - self.bounds.size.height) / 2.0;
int yOrigin = (self.bounds.size.height - self.bounds.size.width) / 2.0;
_orientation = orientation;
if (!self.tableView)
return;
self.tableView.transform = CGAffineTransformIdentity;
self.tableView.frame = CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height);
if (_orientation == EasyTableViewOrientationHorizontal) {
int xOrigin = (self.bounds.size.width - self.bounds.size.height) / 2.0;
int yOrigin = (self.bounds.size.height - self.bounds.size.width) / 2.0;

self.tableView.frame = CGRectMake(xOrigin, yOrigin, self.bounds.size.height, self.bounds.size.width);
self.tableView.transform = CGAffineTransformMakeRotation(-M_PI/2);
self.tableView.frame = CGRectMake(xOrigin, yOrigin, self.bounds.size.height, self.bounds.size.width);
self.tableView.transform = CGAffineTransformMakeRotation(-M_PI/2);

self.tableView.scrollIndicatorInsets = UIEdgeInsetsMake(0.0, 0.0, 0.0, self.bounds.size.height - 7.0);
}
self.tableView.scrollIndicatorInsets = UIEdgeInsetsMake(0.0, 0.0, 0.0, self.bounds.size.height - 7.0);
}
}

- (CGPoint)contentOffset {
Expand Down Expand Up @@ -105,10 +105,10 @@ - (CGSize)contentSize {
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
if ([self.delegate respondsToSelector:@selector(numberOfSectionsInEasyTableView:)]) {
return [self.delegate numberOfSectionsInEasyTableView:self];
}
return 1;
if ([self.delegate respondsToSelector:@selector(numberOfSectionsInEasyTableView:)]) {
return [self.delegate numberOfSectionsInEasyTableView:self];
}
return 1;
}

- (void)reload {
Expand All @@ -118,27 +118,27 @@ - (void)reload {
#pragma mark - Footers and Headers

- (CGFloat)tableView:(UITableView*)tableView heightForHeaderInSection:(NSInteger)section {
if ([self.delegate respondsToSelector:@selector(easyTableView:viewForHeaderInSection:)]) {
UIView *headerView = [self.delegate easyTableView:self viewForHeaderInSection:section];
if ([self.delegate respondsToSelector:@selector(easyTableView:viewForHeaderInSection:)]) {
UIView *headerView = [self.delegate easyTableView:self viewForHeaderInSection:section];

if (self.orientation == EasyTableViewOrientationHorizontal)
return headerView.frame.size.width;
else
else
return headerView.frame.size.height;
}
return 0.0;
}
return 0.0;
}

- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
if ([self.delegate respondsToSelector:@selector(easyTableView:viewForFooterInSection:)]) {
UIView *footerView = [self.delegate easyTableView:self viewForFooterInSection:section];
if ([self.delegate respondsToSelector:@selector(easyTableView:viewForFooterInSection:)]) {
UIView *footerView = [self.delegate easyTableView:self viewForFooterInSection:section];

if (self.orientation == EasyTableViewOrientationHorizontal)
return footerView.frame.size.width;
else
else
return footerView.frame.size.height;
}
return 0.0;
}
return 0.0;
}

- (UIView *)viewToHoldSectionView:(UIView *)sectionView {
Expand All @@ -161,36 +161,59 @@ - (UIView *)viewToHoldSectionView:(UIView *)sectionView {
}

- (UIView*)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
if ([self.delegate respondsToSelector:@selector(easyTableView:viewForHeaderInSection:)]) {
if ([self.delegate respondsToSelector:@selector(easyTableView:viewForHeaderInSection:)]) {
UIView *sectionView = [self.delegate easyTableView:self viewForHeaderInSection:section];

return [self viewToHoldSectionView:sectionView];
}
return nil;
}
return nil;
}

- (UIView*)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {
if ([self.delegate respondsToSelector:@selector(easyTableView:viewForFooterInSection:)]) {
if ([self.delegate respondsToSelector:@selector(easyTableView:viewForFooterInSection:)]) {
UIView *sectionView = [self.delegate easyTableView:self viewForFooterInSection:section];

return [self viewToHoldSectionView:sectionView];
}
return nil;
}
return nil;
}

#pragma mark - ScrollViewDelegate

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
if ([self.delegate respondsToSelector:@selector(easyTableViewWillBeginDragging:)])
[self.delegate easyTableViewWillBeginDragging:self];
}

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
if ([self.delegate respondsToSelector:@selector(easyTableViewDidEndDragging:willDecelerate:)])
[self.delegate easyTableViewDidEndDragging:self willDecelerate:decelerate];
}

- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView {
if ([self.delegate respondsToSelector:@selector(easyTableViewWillBeginDecelerating:)])
[self.delegate easyTableViewWillBeginDecelerating:self];
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
if ([self.delegate respondsToSelector:@selector(easyTableViewDidEndDecelerating:)])
[self.delegate easyTableViewDidEndDecelerating:self];
}

#pragma mark - TableViewDelegate

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if ([self.delegate respondsToSelector:@selector(easyTableView:didSelectRowAtIndexPath:)]) {
[self.delegate easyTableView:self didSelectRowAtIndexPath:indexPath];
}
[self.delegate easyTableView:self didSelectRowAtIndexPath:indexPath];
}
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if ([self.delegate respondsToSelector:@selector(easyTableView:heightOrWidthForCellAtIndexPath:)]) {
return [self.delegate easyTableView:self heightOrWidthForCellAtIndexPath:indexPath];
}
return tableView.rowHeight;
if ([self.delegate respondsToSelector:@selector(easyTableView:heightOrWidthForCellAtIndexPath:)]) {
return [self.delegate easyTableView:self heightOrWidthForCellAtIndexPath:indexPath];
}
return tableView.rowHeight;
}

#pragma mark - TableViewDataSource
Expand All @@ -200,7 +223,7 @@ - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger
}

- (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell * cell = [self.delegate easyTableView:self cellForRowAtIndexPath:indexPath];
UITableViewCell * cell = [self.delegate easyTableView:self cellForRowAtIndexPath:indexPath];

// Cell deletion must be enabled by the EasyTableView owner
BOOL allowCellDeletion = NO;
Expand All @@ -216,16 +239,16 @@ - (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(
[cell addGestureRecognizer:panGesture];
}

// Rotate if needed
if ((self.orientation == EasyTableViewOrientationHorizontal) &&
CGAffineTransformEqualToTransform(cell.contentView.transform, CGAffineTransformIdentity)) {
int xOrigin = (cell.bounds.size.width - cell.bounds.size.height) / 2.0;
int yOrigin = (cell.bounds.size.height - cell.bounds.size.width) / 2.0;
// Rotate if needed
if ((self.orientation == EasyTableViewOrientationHorizontal) &&
CGAffineTransformEqualToTransform(cell.contentView.transform, CGAffineTransformIdentity)) {
int xOrigin = (cell.bounds.size.width - cell.bounds.size.height) / 2.0;
int yOrigin = (cell.bounds.size.height - cell.bounds.size.width) / 2.0;

cell.contentView.frame = CGRectMake(xOrigin, yOrigin, cell.bounds.size.height, cell.bounds.size.width);
cell.contentView.transform = CGAffineTransformMakeRotation(M_PI/2.0);
}
return cell;
cell.contentView.frame = CGRectMake(xOrigin, yOrigin, cell.bounds.size.height, cell.bounds.size.width);
cell.contentView.transform = CGAffineTransformMakeRotation(M_PI/2.0);
}
return cell;
}

#pragma mark - Pan gesture recognizer (for cell deletion)
Expand All @@ -246,7 +269,12 @@ - (void)handlePanGesture:(UIPanGestureRecognizer *)gesture {

CGRect oversizedRect = CGRectInset(gesture.view.frame, -DELETE_THRESHOLD, -DELETE_THRESHOLD);
BOOL doesIntersect = CGRectIntersectsRect(oversizedRect, self.frame);


// Notify delegate that cell deletion is in process. It's helpful
// to know what's going on in cases where an EasyTableView may be
// hidden from sight if there is no user activity.
[self informDelegateOfPendingCellDeletion];

switch (gesture.state) {
case UIGestureRecognizerStateBegan: {

Expand All @@ -268,7 +296,8 @@ - (void)handlePanGesture:(UIPanGestureRecognizer *)gesture {
case UIGestureRecognizerStateChanged: {
gesture.view.center = CGPointMake(centerLocation.x + translation.x, centerLocation.y + translation.y);

[self setView:gesture.view asSelected:doesIntersect];
// Provide an opportunity for any UI updates
[self informDelegateCell:(UITableViewCell *)gesture.view deletionIsEminent:!doesIntersect];
break;
}

Expand All @@ -292,7 +321,8 @@ - (void)handlePanGesture:(UIPanGestureRecognizer *)gesture {
if (self.orientation == EasyTableViewOrientationHorizontal) {
gesture.view.transform = CGAffineTransformRotate(gesture.view.transform, M_PI/2);
}
[self setView:gesture.view asSelected:NO];
// Provide an opportunity for any UI updates
[self informDelegateCell:(UITableViewCell *)gesture.view deletionIsEminent:NO];

// Reinsert into orginal layer of view hierarchy
[cellSuperview addSubview:gesture.view];
Expand All @@ -317,7 +347,9 @@ - (void)handlePanGesture:(UIPanGestureRecognizer *)gesture {
} completion:^(BOOL finished) {
// Restore the cell for reuse
gesture.view.transform = CGAffineTransformIdentity;
[self setView:gesture.view asSelected:NO];

// Provide an opportunity for any UI updates
[self informDelegateCell:(UITableViewCell *)gesture.view deletionIsEminent:NO];

// Delete the cell only after animation has completed.
// Otherwise cell could disappear prematurely.
Expand All @@ -335,14 +367,15 @@ - (void)handlePanGesture:(UIPanGestureRecognizer *)gesture {
}
}

- (void)setView:(UIView *)view asSelected:(BOOL)selected {
if (selected) {
view.layer.borderColor = [UIColor colorWithRed:1 green:0 blue:0 alpha:0.5].CGColor;
view.layer.borderWidth = 8.0;
- (void)informDelegateOfPendingCellDeletion {
if ([self.delegate respondsToSelector:@selector(easyTableViewHasPendingCellDeletion:)]) {
[self.delegate easyTableViewHasPendingCellDeletion:self];
}
else {
view.layer.borderColor = nil;
view.layer.borderWidth = 0.0;
}

- (void)informDelegateCell:(UITableViewCell *)cell deletionIsEminent:(BOOL)eminent {
if ([self.delegate respondsToSelector:@selector(easyTableView:cell:deletionIsEminent:)]) {
[self.delegate easyTableView:self cell:cell deletionIsEminent:eminent];
}
}

Expand Down
14 changes: 14 additions & 0 deletions Classes/EasyTableViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,16 @@ - (void)borderIsSelected:(BOOL)selected forView:(UIView *)view {
borderView.image = [UIImage imageNamed:borderImageName];
}

- (void)indicateView:(UIView *)view pendingDeletion:(BOOL)pendingDeletion {
if (pendingDeletion) {
view.layer.borderColor = [UIColor colorWithRed:1 green:0 blue:0 alpha:0.5].CGColor;
view.layer.borderWidth = 8.0;
}
else {
view.layer.borderColor = nil;
view.layer.borderWidth = 0.0;
}
}

#pragma mark - EasyTableViewDelegate

Expand Down Expand Up @@ -208,6 +218,10 @@ - (void)easyTableView:(EasyTableView *)easyTableView didDeleteCellAtIndexPath:(N
}
}

- (void)easyTableView:(EasyTableView *)easyTableView cell:(UITableViewCell *)cell deletionIsEminent:(BOOL)eminent {
[self indicateView:cell pendingDeletion:eminent];
}

#pragma mark - Optional EasyTableView delegate methods for section headers and footers

#ifdef SHOW_MULTIPLE_SECTIONS
Expand Down

0 comments on commit 77577a3

Please sign in to comment.