iOS 利用長按手勢移動 Table View Cells,ioscells

來源:互聯網
上載者:User

iOS 利用長按手勢移動 Table View Cells,ioscells

本文譯自: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 進行重排。這裡可以下載到已經實現好了工程。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.