UITableViewCell單Section及多Section的Cell手勢(shì)拖動(dòng)

前言

最近項(xiàng)目中需要拖動(dòng)UITableViewCell進(jìn)行排序,基于系統(tǒng)的方法只能進(jìn)入編輯模式觸發(fā),且沒(méi)有Section間的控制方法,UI也有局限性,所以參考網(wǎng)上做法實(shí)現(xiàn)如下效果:


image.png

以實(shí)現(xiàn)不同的Section間單獨(dú)處理。

首先

cell的操作圖片上添加長(zhǎng)按手勢(shì),根據(jù)state的值進(jìn)行操作

- (void)dragCell:(UITableViewCell *)cell recognizer:(UILongPressGestureRecognizer *)longPress {
    UIGestureRecognizerState state = longPress.state;
    switch (state) {
        case UIGestureRecognizerStateBegan: {
            NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
            if (indexPath) {
                self.sourceIndexPath = indexPath;
                self.snapshot = [self customSnapshoFromView:cell];
                __block CGPoint center = cell.center;
                self.snapshot.center = center;
                self.snapshot.alpha = 0.0;
                [self.tableView addSubview:self.snapshot];

                [UIView animateWithDuration:0.25 animations:^{
                    self.snapshot.center = center;
                    self.snapshot.transform = CGAffineTransformMakeScale(1.05, 1.05);
                    self.snapshot.alpha = 0.98;
                    cell.alpha = 0.0f;
                } completion:^(BOOL finished) {
                    cell.hidden = YES;
                }];
            }

            break;
        }
            
        case UIGestureRecognizerStateChanged: {
            CGPoint location = [longPress locationOfTouch:0 inView:self.tableView];
            CGPoint center = self.snapshot.center;
            center.y = location.y;
            self.snapshot.center = center;
            NSIndexPath *changedIndexPath = [self.tableView indexPathForRowAtPoint:location];

            // 是否位置變動(dòng)
            if (changedIndexPath && ![changedIndexPath isEqual:self.sourceIndexPath]) {
                if (changedIndexPath.section != self.sourceIndexPath.section) {
                    return;
                }
                // 要拖動(dòng)的數(shù)據(jù)
                NSArray *sectionArry = self.getAdapterArry[self.sourceIndexPath.section];
                // 移動(dòng)數(shù)據(jù)交換
                NSMutableArray *sourceSectionArry = sectionArry.mutableCopy;
                [sourceSectionArry exchangeObjectAtIndex:changedIndexPath.row withObjectAtIndex:self.sourceIndexPath.row];
                // 更新數(shù)據(jù)源
                [self.getAdapterArry replaceObjectAtIndex:self.sourceIndexPath.section withObject:sourceSectionArry];
                [[YSCommonDataManager shareManager] addtoKLineIndexStyleSet:self.getAdapterArry];
                
                [self.tableView moveRowAtIndexPath:self.sourceIndexPath toIndexPath:changedIndexPath];
                self.sourceIndexPath = changedIndexPath;
            }
            
            break;
        }
        // 最后就是默認(rèn)(拖動(dòng)完成或者未拖動(dòng))
        default: {
            // Clean up.
            UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:self.sourceIndexPath];
            
            [UIView animateWithDuration:0.25 animations:^{
                self.snapshot.center = cell.center;
                self.snapshot.transform = CGAffineTransformIdentity;
                self.snapshot.alpha = 0.0;
                cell.alpha = 1.0f;
            } completion:^(BOOL finished) {
                cell.hidden = NO;
                [self.snapshot removeFromSuperview];
                self.snapshot = nil;
            }];
            self.sourceIndexPath = nil;
            
            break;
        }
    }
}

接著

為了能實(shí)現(xiàn)懸浮的效果,需要?jiǎng)?chuàng)建一個(gè)快照視圖。
@property (nonatomic, strong) UIView *snapshot;

- (UIView *)customSnapshoFromView:(UIView *)inputView {
    UIView *snapshot = nil;
    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;
}
  • UIGestureRecognizerStateBegan時(shí),獲取被移動(dòng)cell的起始位置sourceIndexPath,將snapshot快照視圖加入到tableView上,隱藏原來(lái)的cell
  • UIGestureRecognizerStateChanged時(shí),獲取到按壓手勢(shì)的偏移位置,調(diào)整snapshot的位置,得到快照被拖移到的新位置changedIndexPath,后根據(jù)
    // 是否位置變動(dòng)
    if (changedIndexPath && ![changedIndexPath isEqual:self.sourceIndexPath]) { if (changedIndexPath.section != self.sourceIndexPath.section) { return; } }
    來(lái)隔斷不同section間的拖動(dòng)。以及進(jìn)行數(shù)據(jù)源交換,cell交換,更新sourceIndexPath等操作。
  • 最后在default狀態(tài),根據(jù)最新的sourceIndexPath來(lái)完成拖動(dòng)完成或者失敗的動(dòng)畫(huà)效果。

至此

完成了單Section及多Section的Cell手勢(shì)拖動(dòng)。

參考文章和源碼:
iOS UITableView可以拖動(dòng)排序的Cell

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容