Abacus Updates

Swipeable UITableView Headers – An Open Source Library

Like the pull to refresh gesture, swiping a list item has become de facto standard for ancillary actions. Across iOS, apps support this shortcut for the common application actions to be taken on an item. Abacus was already using swipe to approve individual items, but we wanted to add an “approve all” function to our iOS mobile app in order to speed up the approval process.

The current standard solution for bulk editing is to have a clunky “edit” → “select” → “action” flow or add a dedicated button similar to Google Inbox. However, we really liked the new approach that BillGuard implemented, which was a swipeable section. We decided it was the right interaction for the inbox and card transactions section of Abacus for iOS. After searching for an existing implementation and not finding one, we decided to build it ourselves.

Previously, we used MCSwipeTableViewCell to support swiping behavior for individual cells and are grateful to its authors and contributors. However, we ultimately decided that in order to support the behavior we were looking for, we needed to implement our own solution. We wanted something that would support both individually swiped cells, as well as header-swiping behavior for a section or group of items. We decided to open source the underlying class and left it flexible to be implemented as needed depending on your use case.

Using AbacusSwipeableTableViewCell

 

For individually swiped cells, AbacusSwipeableTableViewCell has a leftTriggerView and rightTriggerView and matching leftTriggerColor and rightTriggerColor properties. These will be revealed behind your cell’s content while swiping to indicate what action will be taken on the item.

UILabel *l = [[UILabel alloc] init];
l.text = @”left”;
cell.leftTriggerView = l;

UILabel *r = [[UILabel alloc] init];
r.text = @”right”;
cell.rightTriggerView = r;

cell.leftTriggerColor = [UIColor redColor];
cell.rightTriggerColor = [UIColor purpleColor];

In order for a cell to actually be swipeable, set its swipeableDirections property

cell.swipeableDirections = AbacusSwipeableTableViewCellDirectionRight | AbacusSwipeableTableViewCellDirectionLeft;

Once a swipe occurs (that is to say, fully triggers), the triggerHandler fires for the cell that is swiped, if it was previously set:

cell.triggerHandler = ^(AbacusSwipeableTableViewCellDirection dir) {
// do something fun!
};

To support the header swipe behavior, we’ve exposed the property childTableViewCells which is expected to return an array of cells to act as children. These will follow the panning behavior of the “header” cell on which this block is set.

cell.childTableViewCells = ^NSArray*() {
// return an array of instances to act as “children”
}

Headers are not constrained to a UITableView’s “sections” and “rows” semantics. You can have multiple “header” swipe-able cells inside a single section that trigger swipes on any subset of cells. You could even have a swipe-able cell that triggers swipes on arbitrary cells in multiple sections but for the sake of your users, please don’t do that.

While we happen to be using an internal class that acts as a dataSource and delegate to our UITableViews, we have built this in a way that is flexible enough to fit any implementation of a UITableView.

We hope this is helpful to the community. We fully encourage bug reports, feature and Github pull requests.

 

Do you enjoy making complex workflows simple with interactions like this? We’re always looking for great engineering and product talent. View our open positions and apply today!

Related Posts