利用长按手势移动 Table View Cells
来源:互联网 发布:java web框架 编辑:程序博客网 时间:2024/05/23 20:47
利用长按手势移动 Table View Cells
本文转载自:破船之家http://beyondvincent.com/2014/03/26/2014-03-26-cookbook-moving-table-view-cells-with-a-long-press-gesture/
本文译自:Cookbook: Moving Table View Cells with a Long Press Gesture
目录:
- 你需要什么?
- 如何做?
- 如何将其利用至UICollectionView上?
- 何去何从?
本次的 cookbook-style 教程中介绍如何通过长按手势来移动 table view中的cell,这种操作方式就像苹果自家的天气 App 一样。
你可以直接把本文中的到吗添加到你的工程中,或者将其添加到我为你创建好的 starter project 中,也可以下载本文的完整示例工程。
你需要什么?
- UILongGestureRecognizer
- UITableView (可以用 UICollectionView 替代之)
- UITableViewController (可以用 UIViewController 或 UICollectionViewController 替代之)
- 5 分钟。
如何做?
首先给 table view 添加一个 UILongGestureRecognizer
。可以在 table view controller 的 viewDidLoad
方法中添加。
123
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(longPressGestureRecognized:)];[self.tableView addGestureRecognizer:longPress];
记者为 gesture recognizer 添加 action 方法。该方法首先应该获取到在 table view 中长按的位置,然后找出这个位置对应的 cell 的 index。记住:这里获取到的 index path 有可能为 nil(例如,如果用户长按在 table view的section header上)。
12345678910
- (IBAction)longPressGestureRecognized:(id)sender {UILongPressGestureRecognizer *longPress = (UILongPressGestureRecognizer *)sender;UIGestureRecognizerState state = longPress.state;CGPoint location = [longPress locationInView:self.tableView];NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:location];// More coming soon...}
接着你需要处理UIGestureRecognizerStateBegan
分支。如果获取到一个有效的 index path(non-nil),就去获取对应的 UITableViewCell
,并利用一个 helper 方法获取这个 table view cell 的 snapshot view。然后将这个 snapshot view 添加到 table view 中,并将其 center 到对应的 cell上。
为了更好的用户体验,以及更自然的效果,在这里我把原始 cell 的背景设置为黑色,并给 snapshot view 增加淡入效果,让 snapshot view 比 原始 cell 稍微大一点,将它的Y坐标偏移量与手势的位置的Y轴对齐。这样处理之后,cell 就像从 table view 中跳出,然后浮在上面,并捕捉到用户的手指。
12345678910111213141516171819202122232425262728293031323334
static UIView *snapshot = nil; ///< A snapshot of the row user is moving.static NSIndexPath *sourceIndexPath = nil; ///< Initial index path, where gesture begins.switch (state) {case UIGestureRecognizerStateBegan: {if (indexPath) {sourceIndexPath = indexPath;UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];// Take a snapshot of the selected row using helper method.snapshot = [self customSnapshotFromView:cell];// Add the snapshot as subview, centered at cell's center...__block CGPoint center = cell.center;snapshot.center = center;snapshot.alpha = 0.0;[self.tableView addSubview:snapshot];[UIView animateWithDuration:0.25 animations:^{// Offset for gesture location.center.y = location.y;snapshot.center = center;snapshot.transform = CGAffineTransformMakeScale(1.05, 1.05);snapshot.alpha = 0.98;// Black out.cell.backgroundColor = [UIColor blackColor];} completion:nil];}break;}// More coming soon...}
将下面的方法添加到 .m 文件的尾部。该方法会根据传入的 view,返回一个对应的 snapshot view。
1234567891011
- (UIView *)customSnapshotFromView:(UIView *)inputView {UIView *snapshot = [inputView snapshotViewAfterScreenUpdates:YES];snapshot.layer.masksToBounds = NO;snapshot.layer.cornerRadius = 0.0;snapshot.layer.shadowOffset = CGSizeMake(-5.0, 0.0);snapshot.layer.shadowRadius = 5.0;snapshot.layer.shadowOpacity = 0.4;return snapshot;}
当手势移动的时候,也就是UIGestureRecognizerStateChanged
分支,此时需要移动 snapshot view(只需要设置它的 Y 轴偏移量即可)。如果手势移动的距离对应到另外一个 index path,就需要告诉 table view,让其移动 rows。同时,你需要对 data source 进行更新:
1234567891011121314151617181920
case UIGestureRecognizerStateChanged: {CGPoint center = snapshot.center;center.y = location.y;snapshot.center = center;// Is destination valid and is it different from source?if (indexPath && ![indexPath isEqual:sourceIndexPath]) {// ... update data source.[self.objects exchangeObjectAtIndex:indexPath.row withObjectAtIndex:sourceIndexPath.row];// ... move the rows.[self.tableView moveRowAtIndexPath:sourceIndexPath toIndexPath:indexPath];// ... and update source so it is in sync with UI changes.sourceIndexPath = indexPath;}break;}// More coming soon...
最后,当手势结束或者取消时,table view 和 data source 都是最新的。你所需要做的事情就是将 snapshot view 从 table view 中移除,并把 cell 的背景色还原为白色。
为了提升用户体验,我们将 snapshot view 淡出,并让其尺寸变小至与 cell 一样。这样看起来就像把 cell 放回原处一样。
123456789101112131415161718192021
default: {// Clean up.UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:sourceIndexPath];[UIView animateWithDuration:0.25 animations:^{snapshot.center = cell.center;snapshot.transform = CGAffineTransformIdentity;snapshot.alpha = 0.0;// Undo the black-out effect we did.cell.backgroundColor = [UIColor whiteColor];} completion:^(BOOL finished) {[snapshot removeFromSuperview];snapshot = nil;}];sourceIndexPath = nil;break;}
就这样,搞定了!编译并运行程序,现在可以通过长按手势对 tableview cells重新排序!
你可以在 GitHub 上下载到完整的示例工程。
如何将其利用至UICollectionView上?
假设你已经有一个示例工程使用了 UICollectionView
,那么你可以很简单的就使用上本文之前介绍的代码。所需要做的事情就是用 self.collectionView
替换掉 self.tableView
,并更新一下获取和移动 UICollectionViewCell
的调用方法。
这里有个练习,从 GitHub上 checkout 出 UICollectionView 的starter project,然后将 tap-和-hold 手势添加进去以对 cells 进行重排。这里可以下载到已经实现好了工程。
- 利用长按手势移动 Table View Cells
- 利用长按手势移动 Table View Cells
- 利用长按手势移动 Table View Cells
- 利用长按手势移动 Table View Cells
- 利用长按手势移动TableView中的Cell
- Customize Table View Cells for UITableView
- Table View Cells With Varying Row Heights
- iOS tableViewCell 的移动操作 (添加长按手势)
- 4.8 Enabling Swipe Deletion of Table View Cells
- 4.10 Displaying Context Menus on Table View Cells
- UITableView Class 参考 (1)<Creating Table View Cells>
- Dynamically size the height of the table view cells
- 自定义view的点击、长按、及长按手势监听事件
- 手势:长按
- 长按手势实现
- iOS 长按手势
- iOS 长按手势
- UILongPressGestureRecognizer长按手势
- Apriori 算法关联分析
- 237. Delete Node in a Linked List
- REST CURL
- Eclipse环境进行Android apk开发问题及解决方法记录(一)
- React实现表单数据的添加与删除
- 利用长按手势移动 Table View Cells
- 376.[LeetCode]Wiggle Subsequence
- 浅谈RobotArt快捷键
- 【BZOJ】4668 冷战
- Apriori算法
- 基于DFS的算法题
- 165.Validate Binary Search Tree
- CVBS转MIPI YUV 信号芯片
- 斐波那契数列