溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

iOS怎么使用UICollectionView實(shí)現(xiàn)拖拽移動單元格

發(fā)布時間:2022-04-27 10:27:04 來源:億速云 閱讀:319 作者:iii 欄目:開發(fā)技術(shù)

這篇“iOS怎么使用UICollectionView實(shí)現(xiàn)拖拽移動單元格”文章的知識點(diǎn)大部分人都不太理解,所以小編給大家總結(jié)了以下內(nèi)容,內(nèi)容詳細(xì),步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“iOS怎么使用UICollectionView實(shí)現(xiàn)拖拽移動單元格”文章吧。

一.介紹

iOS9提供API實(shí)現(xiàn)單元格排序呢功能,使用UICollectionView及其代理方法.iOS9之后有自帶方法可以實(shí)現(xiàn)該效果,只需添加長按手勢,實(shí)現(xiàn)手勢方法和調(diào)用iOS9的API交換數(shù)據(jù),iOS9之前需要自己寫方法實(shí)現(xiàn)這效果,除了要添加長按手勢,這里還需要利用截圖替換原理,手動計算移動位置來處理視圖交換和數(shù)據(jù)交換.

二.方法和步驟

1.創(chuàng)建工程項(xiàng)目和視圖控制器,如下圖

iOS怎么使用UICollectionView實(shí)現(xiàn)拖拽移動單元格

2.聲明對象和設(shè)置代理和數(shù)據(jù)源代理

@interface ViewController ()<UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout>
 
@property (nonatomic, strong) NSMutableArray *dataArr;
@property (nonatomic, strong) UICollectionView *collectionView;
/**之前選中cell的NSIndexPath*/
@property (nonatomic, strong) NSIndexPath *oldIndexPath;
/**單元格的截圖*/
@property (nonatomic, strong) UIView *snapshotView;
/**之前選中cell的NSIndexPath*/
@property (nonatomic, strong) NSIndexPath *moveIndexPath;
 
@end

3.初始化UICollectionView,并添加長按手勢,在viewDidLoad中初始化

CGFloat SCREEN_WIDTH = self.view.frame.size.width;
    UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
    flowLayout.itemSize = CGSizeMake((SCREEN_WIDTH-40.0)/3, (SCREEN_WIDTH-40.0)/3);
    UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 50.0, SCREEN_WIDTH, (SCREEN_WIDTH-40.0)/3+20.0) collectionViewLayout:flowLayout];
    collectionView.dataSource = self;
    collectionView.delegate = self;
    collectionView.backgroundColor = [UIColor whiteColor];
    [collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"uicollectionviewcell"];
    [self.view addSubview:self.collectionView = collectionView];
    
    // 添加長按手勢
    UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handlelongGesture:)];
    [collectionView addGestureRecognizer:longPress];

4.實(shí)例化數(shù)據(jù)源,(50個隨機(jī)顏色,透明度0.8),在viewDidLoad中初始化

self.dataArr = [[NSMutableArray alloc] init];
for (NSInteger index = 0; index < 50; index ++) {
        CGFloat hue = (arc4random()%256/256.0); //0.0 到 1.0
        CGFloat saturation = (arc4random()%128/256.0)+0.5; //0.5 到 1.0
        CGFloat brightness = (arc4random()%128/256.0)+0.5; //0.5 到 1.0
        UIColor *color = [UIColor colorWithHue:hue saturation:saturation brightness:brightness alpha:0.5];
        [self.dataArr addObject:color];
    }

5.實(shí)現(xiàn)UICollectionView的UICollectionViewDataSource的兩個必須實(shí)現(xiàn)的方法

#pragma mark - UICollectionViewDataSource
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
    return self.dataArr.count;
}
 
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"uicollectionviewcell" forIndexPath:indexPath];
    cell.backgroundColor = self.dataArr[indexPath.row];
    return cell;
}

6.重點(diǎn)來了,實(shí)現(xiàn)長按手勢方法

#pragma mark - 長按手勢
- (void)handlelongGesture:(UILongPressGestureRecognizer *)longPress
{
    if ([[[UIDevice currentDevice] systemVersion] floatValue] < 9.0) {
        [self action:longPress];
    } else {
        [self iOS9_Action:longPress];
    }
}

7.iOS9之后的實(shí)現(xiàn)

#pragma mark - iOS9 之后的方法
- (BOOL)collectionView:(UICollectionView *)collectionView canMoveItemAtIndexPath:(NSIndexPath *)indexPath
{
    // 返回YES允許row移動
    return YES;
}
 
- (void)collectionView:(UICollectionView *)collectionView moveItemAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
{
    //取出移動row數(shù)據(jù)
    id color = self.dataArr[sourceIndexPath.row];
    //從數(shù)據(jù)源中移除該數(shù)據(jù)
    [self.dataArr removeObject:color];
    //將數(shù)據(jù)插入到數(shù)據(jù)源中的目標(biāo)位置
    [self.dataArr insertObject:color atIndex:destinationIndexPath.row];
}
 
- (void)iOS9_Action:(UILongPressGestureRecognizer *)longPress
{
    switch (longPress.state) {
        case UIGestureRecognizerStateBegan:
        { //手勢開始
            //判斷手勢落點(diǎn)位置是否在row上
            NSIndexPath *indexPath = [self.collectionView indexPathForItemAtPoint:[longPress locationInView:self.collectionView]];
            if (indexPath == nil) {
                break;
            }
            UICollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:indexPath];
            [self.view bringSubviewToFront:cell];
            //iOS9方法 移動cell
            [self.collectionView beginInteractiveMovementForItemAtIndexPath:indexPath];
        }
            break;
        case UIGestureRecognizerStateChanged:
        { // 手勢改變
            // iOS9方法 移動過程中隨時更新cell位置
            [self.collectionView updateInteractiveMovementTargetPosition:[longPress locationInView:self.collectionView]];
        }
            break;
        case UIGestureRecognizerStateEnded:
        { // 手勢結(jié)束
            // iOS9方法 移動結(jié)束后關(guān)閉cell移動
            [self.collectionView endInteractiveMovement];
        }
            break;
        default: //手勢其他狀態(tài)
            [self.collectionView cancelInteractiveMovement];
            break;
    }
}

8.iOS9之前的實(shí)現(xiàn)

#pragma mark - iOS9 之前的方法
- (void)action:(UILongPressGestureRecognizer *)longPress
{
    switch (longPress.state) {
        case UIGestureRecognizerStateBegan:
        { // 手勢開始
            //判斷手勢落點(diǎn)位置是否在row上
            NSIndexPath *indexPath = [self.collectionView indexPathForItemAtPoint:[longPress locationInView:self.collectionView]];
            self.oldIndexPath = indexPath;
            if (indexPath == nil) {
                break;
            }
            UICollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:indexPath];
            // 使用系統(tǒng)的截圖功能,得到cell的截圖視圖
            UIView *snapshotView = [cell snapshotViewAfterScreenUpdates:NO];
            snapshotView.frame = cell.frame;
            [self.view addSubview:self.snapshotView = snapshotView];
            // 截圖后隱藏當(dāng)前cell
            cell.hidden = YES;
            
            CGPoint currentPoint = [longPress locationInView:self.collectionView];
            [UIView animateWithDuration:0.25 animations:^{
                snapshotView.transform = CGAffineTransformMakeScale(1.05, 1.05);
                snapshotView.center = currentPoint;
            }];
        }
            break;
        case UIGestureRecognizerStateChanged:
        { // 手勢改變
            //當(dāng)前手指位置 截圖視圖位置隨著手指移動而移動
            CGPoint currentPoint = [longPress locationInView:self.collectionView];
            self.snapshotView.center = currentPoint;
            // 計算截圖視圖和哪個可見cell相交
            for (UICollectionViewCell *cell in self.collectionView.visibleCells) {
                // 當(dāng)前隱藏的cell就不需要交換了,直接continue
                if ([self.collectionView indexPathForCell:cell] == self.oldIndexPath) {
                    continue;
                }
                // 計算中心距
                CGFloat space = sqrtf(pow(self.snapshotView.center.x - cell.center.x, 2) + powf(self.snapshotView.center.y - cell.center.y, 2));
                // 如果相交一半就移動
                if (space <= self.snapshotView.bounds.size.width / 2) {
                    self.moveIndexPath = [self.collectionView indexPathForCell:cell];
                    //移動 會調(diào)用willMoveToIndexPath方法更新數(shù)據(jù)源
                    [self.collectionView moveItemAtIndexPath:self.oldIndexPath toIndexPath:self.moveIndexPath];
                    //設(shè)置移動后的起始indexPath
                    self.oldIndexPath = self.moveIndexPath;
                    break;
                }
            }
        }
            break;
        default:
        { // 手勢結(jié)束和其他狀態(tài)
            UICollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:self.oldIndexPath];
            // 結(jié)束動畫過程中停止交互,防止出問題
            self.collectionView.userInteractionEnabled = NO;
            // 給截圖視圖一個動畫移動到隱藏cell的新位置
            [UIView animateWithDuration:0.25 animations:^{
                self.snapshotView.center = cell.center;
                self.snapshotView.transform = CGAffineTransformMakeScale(1.0, 1.0);
            } completion:^(BOOL finished) {
                // 移除截圖視圖,顯示隱藏的cell并開始交互
                [self.snapshotView removeFromSuperview];
                cell.hidden = NO;
                self.collectionView.userInteractionEnabled = YES;
            }];
        }
            break;
    }
}

三.iOS9之后添加的API如下

// Support for reordering
- (BOOL)beginInteractiveMovementForItemAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(9_0); // returns NO if reordering was prevented from beginning - otherwise YES
- (void)updateInteractiveMovementTargetPosition:(CGPoint)targetPosition NS_AVAILABLE_IOS(9_0);
- (void)endInteractiveMovement NS_AVAILABLE_IOS(9_0);
- (void)cancelInteractiveMovement NS_AVAILABLE_IOS(9_0);

以上就是關(guān)于“iOS怎么使用UICollectionView實(shí)現(xiàn)拖拽移動單元格”這篇文章的內(nèi)容,相信大家都有了一定的了解,希望小編分享的內(nèi)容對大家有幫助,若想了解更多相關(guān)的知識內(nèi)容,請關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI