iOS 拖拽排序实现
2016-11-25 本文已影响365人
马大俊不是啥好人
老早之前说要做这个,主要是看了微博的一个转发,然后发现其实系统已经有自带的功能了。不管怎么样,先写一下基于UIColloctionView的拖曳排序。
在iOS 9之前需要手动截图cell并进行拖曳计算,iOS 9之后存在两个delegate方法
-(BOOL)collectionView:(UICollectionView *)collectionView canMoveItemAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
- (void)collectionView:(UICollectionView *)collectionView moveItemAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath*)destinationIndexPath {
id objc = [_arr objectAtIndex:sourceIndexPath.item];
[_arr removeObject:objc];
[_arr insertObject:objc atIndex:destinationIndexPath.item];
}
实现这两个方法就能实现拖曳排序。一步步来。
首先新建一个UIColloctionViewCell的子类
//
// MoveCollectionViewCell.h
// MJChangeItem
//
// Created by 马家俊 on 16/12/12.
// Copyright © 2016年 MJJ. All rights reserved.
//
#import <UIKit/UIKit.h>
@protocol MoveCollectionViewCellDelegate <NSObject>
- (void)GesturePressDelegate:(UIGestureRecognizer *)gestureRecognizer;
@end
@interface MoveCollectionViewCell : UICollectionViewCell
{
__weak id<MoveCollectionViewCellDelegate>m_MoveCollectionViewCellDelegate;
}
@property (nonatomic, weak) id<MoveCollectionViewCellDelegate> p_MoveCollectionViewCellDelegate;
@property (nonatomic, strong) NSString* cellName;
@end
代码中先定义一个代理MoveCollectionViewCellDelegate,代理中需要实现是cell的长按与拖动手势,其中拖动手势只需要在iOS 9之前的系统中添加。
再添加了一个cellName的属性,待会来重写set方法
到.m文件中
//
// MoveCollectionViewCell.m
// MJChangeItem
//
// Created by 马家俊 on 16/12/12.
// Copyright © 2016年 MJJ. All rights reserved.
//
#import "MoveCollectionViewCell.h"
@interface MoveCollectionViewCell()<UIGestureRecognizerDelegate>
@property(nonatomic,strong) UILabel* nameLab;
@end
@implementation MoveCollectionViewCell
@synthesize p_MoveCollectionViewCellDelegate = m_MoveCollectionViewCellDelegate;
@synthesize nameLab;
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self addGestureCell];
[self addLab];
}
return self;
}
这段是定义个label,添加下delegate,初始化下cell,没啥好说的。
实现下init中的两个方法
//为cell添加手势
-(void)addGestureCell
{
UILongPressGestureRecognizer * longPress =[[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(GesturePress:)];
longPress.delegate = self;
[self addGestureRecognizer:longPress];
if ([[[UIDevice currentDevice] systemVersion] floatValue] <9)
{
UIPanGestureRecognizer * panGes =[[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(GesturePress:)];
panGes.delegate = self;
[self addGestureRecognizer:panGes];
}
}
//为cell添加lab
-(void)addLab
{
nameLab = [UILabel new];
nameLab.font = [UIFont systemFontOfSize:12];
nameLab.textColor = [UIColor grayColor];
nameLab.layer.borderColor = [UIColor grayColor].CGColor;
nameLab.layer.borderWidth = 1;
nameLab.layer.cornerRadius = 5;
nameLab.layer.masksToBounds = YES;
nameLab.textAlignment = NSTextAlignmentCenter;
[self addSubview:nameLab];
}
最后重写下set方法
-(void)setCellName:(NSString *)cellName
{
_cellName = cellName;
nameLab.text = cellName;
nameLab.frame = CGRectMake(0, 0, self.frame.size.width - 5, self.frame.size.height - 5);
nameLab.center = CGPointMake(self.frame.size.width / 2, self.frame.size.height / 2);
}
哦,还有手势对应的方法,代理跳转到vc中实现
- (void)GesturePress:(UIGestureRecognizer *)gestureRecognizer{
if (m_MoveCollectionViewCellDelegate && [m_MoveCollectionViewCellDelegate respondsToSelector:@selector(GesturePressDelegate:)]) {
[m_MoveCollectionViewCellDelegate GesturePressDelegate:gestureRecognizer];
}
}
这是cell的全部代码。。。。
接下来去vc中
所有vc中声明的属性
//
// ViewController.m
// MJChangeItem
//
// Created by 马家俊 on 16/12/12.
// Copyright © 2016年 MJJ. All rights reserved.
//
#import "ViewController.h"
#import "MoveCollectionViewCell.h"
#define K_MAIN_SCREEN_WIDTH [UIScreen mainScreen].bounds.size.width
#define K_MAIN_SCREEN_HEIGHT [UIScreen mainScreen].bounds.size.height
@interface ViewController ()<UICollectionViewDelegate,UICollectionViewDataSource,MoveCollectionViewCellDelegate>
@property(nonatomic,strong) UICollectionView* MJColloctionView;
@property(nonatomic,strong) NSMutableArray* arr;
//iOS9 及之后弃用以下属性
@property(nonatomic,strong) UIView * shotView;
@property(nonatomic,strong) NSIndexPath * indexPath;
@property(nonatomic,strong) NSIndexPath * nextIndexPath;
@property(nonatomic,weak) MoveCollectionViewCell * originalCell;
@end
懒加载初始化个UICollectionView
#define kItemSpace 20
- (UICollectionView *)MJColloctionView
{
if (!MJColloctionView) {
UICollectionViewFlowLayout * layout = [[UICollectionViewFlowLayout alloc] init];
layout.itemSize = CGSizeMake((K_MAIN_SCREEN_WIDTH-(kItemSpace*8))/9, 30);
MJColloctionView = [[UICollectionView alloc]initWithFrame:CGRectMake(0, 44, K_MAIN_SCREEN_WIDTH, K_MAIN_SCREEN_HEIGHT-44) collectionViewLayout:layout];
[MJColloctionView registerClass:[MoveCollectionViewCell class] forCellWithReuseIdentifier:@"MoveCollectionViewCell"];
MJColloctionView.dataSource = self;
MJColloctionView.delegate = self;
MJColloctionView.backgroundColor = [UIColor whiteColor];
}
return MJColloctionView;
}
是线下UIColloction代理
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
return _arr.count;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
MoveCollectionViewCell * cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"MoveCollectionViewCell" forIndexPath:indexPath];
cell.p_MoveCollectionViewCellDelegate = self;
cell.cellName = [_arr objectAtIndex:indexPath.row];
return cell;
}
-(BOOL)collectionView:(UICollectionView *)collectionView canMoveItemAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
- (void)collectionView:(UICollectionView *)collectionView moveItemAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath*)destinationIndexPath {
id objc = [_arr objectAtIndex:sourceIndexPath.item];
[_arr removeObject:objc];
[_arr insertObject:objc atIndex:destinationIndexPath.item];
}
这样至少能够显示出来colloctionview了;
最后要实现的就是拖曳这一个动作了
-(void)GesturePressDelegate:(UIGestureRecognizer *)gestureRecognizer
{
if ([[[UIDevice currentDevice] systemVersion] floatValue] >9) {
switch (gestureRecognizer.state) {
case UIGestureRecognizerStateBegan:{
//判断手势落点位置是否在路径上
NSIndexPath *indexPath = [MJColloctionView indexPathForItemAtPoint:[gestureRecognizer locationInView:self.MJColloctionView]];
if (indexPath == nil) {
break;
}
//在路径上则开始移动该路径上的cell
[MJColloctionView beginInteractiveMovementForItemAtIndexPath:indexPath];
}
break;
case UIGestureRecognizerStateChanged:
//移动过程当中随时更新cell位置
[MJColloctionView updateInteractiveMovementTargetPosition:[gestureRecognizer locationInView:self.MJColloctionView]];
break;
case UIGestureRecognizerStateEnded:
//移动结束后关闭cell移动
[MJColloctionView endInteractiveMovement];
break;
default:
[MJColloctionView cancelInteractiveMovement];
break;
}
}else
{
MoveCollectionViewCell* cell = (MoveCollectionViewCell*)gestureRecognizer.view;
static CGPoint startPoint;
if (gestureRecognizer.state == UIGestureRecognizerStateBegan) {
_shotView = [cell snapshotViewAfterScreenUpdates:NO];
_shotView.center = cell.center;
NSLog(@"%@",cell.description);
NSLog(@"%@",_shotView.description);
[MJColloctionView addSubview:_shotView];
_indexPath = [MJColloctionView indexPathForCell:cell];
_originalCell = cell;
_originalCell.hidden = YES;
startPoint = [gestureRecognizer locationInView:MJColloctionView];
}else if (gestureRecognizer.state == UIGestureRecognizerStateChanged)
{
//获取移动量
CGFloat tranX = [gestureRecognizer locationOfTouch:0 inView:MJColloctionView].x - startPoint.x;
CGFloat tranY = [gestureRecognizer locationOfTouch:0 inView:MJColloctionView].y - startPoint.y;
//进行移动
_shotView.center = CGPointApplyAffineTransform(_shotView.center, CGAffineTransformMakeTranslation(tranX, tranY));
//更新初始位置
startPoint = [gestureRecognizer locationOfTouch:0 inView:MJColloctionView];
for (UICollectionViewCell *cellVisible in [MJColloctionView visibleCells])
{
//移动的截图与目标cell的center直线距离
CGFloat space = sqrtf(pow(_shotView.center.x - cellVisible.center.x, 2) + powf(_shotView.center.y - cellVisible.center.y, 2));
//判断是否替换位置,通过直接距离与重合程度
if (space <= _shotView.frame.size.width/2&&(fabs(_shotView.center.y-cellVisible.center.y) <= _shotView.bounds.size.height/2)) {
_nextIndexPath = [MJColloctionView indexPathForCell:cellVisible];
if (_nextIndexPath.item > _indexPath.item)
{
for(NSInteger i = _indexPath.item; i <_nextIndexPath.item;i++)
{
//移动数据源位置
[_arr exchangeObjectAtIndex:i withObjectAtIndex:i+1];
}
}else
{
for(NSInteger i = _indexPath.item; i <_nextIndexPath.item;i--)
{
//移动数据源位置
[_arr exchangeObjectAtIndex:i withObjectAtIndex:i-1];
}
}
//移动视图cell位置
[MJColloctionView moveItemAtIndexPath:_indexPath toIndexPath:_nextIndexPath];
//更新移动视图的数据
_indexPath = _nextIndexPath;
break;
}
}
}else if (gestureRecognizer.state == UIGestureRecognizerStateEnded)
{
[_shotView removeFromSuperview];
[_originalCell setHidden:NO];
}
}
}
viewDidLoad加下数据
- (void)viewDidLoad {
[super viewDidLoad];
_arr = [[NSMutableArray alloc]initWithArray:[NSArray arrayWithObjects:@"我",@"的",@"背",@"脊",@"如",@"荒",@"丘",@",",@"而",@"你",@"却",@"微",@"笑",@"摆",@"手",@",",@"把",@"它",@"当",@"成",@"整",@"个",@"宇",@"宙", nil]];
[self.view addSubview:self.MJColloctionView];
// Do any additional setup after loading the view, typically from a nib.
}
2016-12-14 10_44_44.gif
就酱..................QAQ