< 返回首页

标哥的笔记,是记录在日常学习技术和日常开发中那些年遇到过的坑!本站为新站,原"标哥的技术博客"中的文章会慢慢移到本站,欢迎收藏本站!
在使用本站过程中,有任何建议请联系标哥! 另,承接App开发、网站开发和微信小程序开发!欢迎联系我们


iOS仿网易新闻栏目拖动重排添加删除效果

 作者:标哥    发布日期:2017-01-11 17:06    阅读量:3037次
 

仿网易新闻栏目选择页面的基本效果,今天抽了点时间教大家如何实现UICollectionView拖动的效果!

其实实现起来并不复杂,这里只是基本的功能,没有实现细节上的修改,连UI都是丑丑的样子,随手画的。

相信大家都使用过网易新闻客户端,里面的效果确定被不少人模仿,很多同类型的app都采用了人家的UI样式,那么今天就教大家如何去实现。

效果图

这是简略的效果图,样子是有点丑,将就看看吧:

标哥的笔记

实现原理

给UICollectionView添加一个手势或者其他方式,在长按时手动触发拖动开始,在移动过程中又要不断手动地更新位置,而在完成时手动触发完成操作,在取消时也要手动触发取消移动操作。

而要实现移动,必须设置是否可移动。比如我们的demo中第一个分区是要求移动的,而第二个分区是不允许移动的,因此我们需要通过代理来设置是否可移动。

在移动完成时,会有代理回调,此时我们要做的就是交换数据源来更新。

移动API介绍

首先我们必须要明确,这几个API是在iOS9之后才能使用的。这几个API来配合起来使用,才能最终达到我们期望的效果。

// 开始
- (BOOL)beginInteractiveMovementForItemAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(9_0); 

// 更新位置
- (void)updateInteractiveMovementTargetPosition:(CGPoint)targetPosition NS_AVAILABLE_IOS(9_0);

// 完成
- (void)endInteractiveMovement NS_AVAILABLE_IOS(9_0);

// 取消
- (void)cancelInteractiveMovement NS_AVAILABLE_IOS(9_0);

这四个API组合起来才是完整的动作。

添加长按手势

我们需要将手势放到CollectionView上,因为我们要的是操作全范围的!

self.collectionView.pagingEnabled = NO;
    
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(onLongPressed:)];
[self.collectionView addGestureRecognizer:longPress];

处理手势

这个基本是固定的,大家可以copy一下我的代码过去用就可以了:

- (void)onLongPressed:(UILongPressGestureRecognizer *)sender {
  CGPoint point = [sender locationInView:sender.view];
  NSIndexPath *indexPath = [self.collectionView indexPathForItemAtPoint:point];
  
  // 只允许第一区可移动
  if (indexPath.section != 0) {
    return;
  }
  
  switch (sender.state) {
    case UIGestureRecognizerStateBegan: {
      if (indexPath) {
        [self.collectionView beginInteractiveMovementForItemAtIndexPath:indexPath];
      }
      break;
    }
    case UIGestureRecognizerStateChanged: {
        [self.collectionView updateInteractiveMovementTargetPosition:point];
      break;
    }
    case UIGestureRecognizerStateEnded: {
      [self.collectionView endInteractiveMovement];
      break;
    }
    default: {
      [self.collectionView cancelInteractiveMovement];
      break;
    }
  }
}

是否允许移动

这里是只有在编辑状态下且第一分区才能拖动重排,所以通过添加条件来控制是否可移动:

- (BOOL)collectionView:(UICollectionView *)collectionView canMoveItemAtIndexPath:(NSIndexPath *)indexPath {
  if (self.isEditing && indexPath.section == 0) {
    return YES;
  }
  
  return NO;
}

完成移动更新源

我们只有第一分区可以操作,而这里只有一个数组,所以直接交换一下数据源就OK了:

- (void)collectionView:(UICollectionView *)collectionView moveItemAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath {
  if (sourceIndexPath.section == 0 && destinationIndexPath.section == 0) {
    [self.firstList exchangeObjectAtIndex:sourceIndexPath.item withObjectAtIndex:destinationIndexPath.item];
  }
}

添加删除移动效果

在点击第一分区时或者第二分区的cell时,会自动移动到第二分区或者第一分区。我们希望有移动的动画效果的话,就需要通过collectionview提供的API来完成,而编辑状态下有删除按钮,而到二分区时就不能显示,而在一分区在编辑状态下又可以显示:

#pragma mark - UICollectionViewDelegate
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
  if (indexPath.section == 0) {
    if (self.isEditing) {
      TestModel *model = [self.secondList hyb_objectAtIndex:indexPath.item];
      [self.firstList addObject:model];
      [self.secondList removeObject:model];
      
      NSInteger index = self.firstList.count - 1;
      if (self.firstList.count == 0) {
        index = 0;
      }
      
      TestColumnCell *cell = (TestColumnCell *)[collectionView cellForItemAtIndexPath:indexPath];
      cell.isEditing = NO;
      [collectionView moveItemAtIndexPath:indexPath toIndexPath:[NSIndexPath indexPathForItem:index inSection:1]];
      [self saveColumns];
    } else {
      // 选择某一个
    }
  } else {
    TestModel *model = [self.firstList hyb_objectAtIndex:indexPath.item];
    [self.secondList addObject:model];
    [self.firstList removeObject:model];
    
    NSInteger index = self.secondList.count - 1;
    if (self.secondList.count == 0) {
      index = 0;
    }

    if (self.isEditing) {
      TestColumnCell *cell = (TestColumnCell *)[collectionView cellForItemAtIndexPath:indexPath];
      cell.isEditing = YES;
    }
    
    [collectionView moveItemAtIndexPath:indexPath toIndexPath:[NSIndexPath indexPathForItem:index inSection:0]];
    [self saveColumns];
  }
  
  [collectionView reloadData];
}

小结

大家不要找我要完整的Demo了啊,这里已经包含所有核心重排功能的代码了。本篇文章仅仅是将个人所写的demo的部分抽出来,不希望大家看到别的demo功能,因此就不公开了!


承接:ThinkPHP项目开发、网站项目开发、微信项目开发、微信小程序项目开发、App开发,欢迎联系标哥QQ632840804