老早之前說(shuō)要做這個(gè)蛇尚,主要是看了微博的一個(gè)轉(zhuǎn)發(fā),然后發(fā)現(xiàn)其實(shí)系統(tǒng)已經(jīng)有自帶的功能了匆笤。不管怎么樣,先寫(xiě)一下基于UIColloctionView的拖曳排序庶诡。
在iOS 9之前需要手動(dòng)截圖cell并進(jìn)行拖曳計(jì)算咆课,iOS 9之后存在兩個(gè)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];
}
實(shí)現(xiàn)這兩個(gè)方法就能實(shí)現(xiàn)拖曳排序。一步步來(lái)喇澡。
首先新建一個(gè)UIColloctionViewCell的子類(lèi)
//
// 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
代碼中先定義一個(gè)代理MoveCollectionViewCellDelegate撩幽,代理中需要實(shí)現(xiàn)是cell的長(zhǎng)按與拖動(dòng)手勢(shì)箩艺,其中拖動(dòng)手勢(shì)只需要在iOS 9之前的系統(tǒng)中添加艺谆。
再添加了一個(gè)cellName的屬性拜英,待會(huì)來(lái)重寫(xiě)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;
}
這段是定義個(gè)label,添加下delegate虫给,初始化下cell侠碧,沒(méi)啥好說(shuō)的。
實(shí)現(xiàn)下init中的兩個(gè)方法
//為cell添加手勢(shì)
-(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];
}
最后重寫(xiě)下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);
}
哦药蜻,還有手勢(shì)對(duì)應(yīng)的方法替饿,代理跳轉(zhuǎn)到vc中實(shí)現(xiàn)
- (void)GesturePress:(UIGestureRecognizer *)gestureRecognizer{
if (m_MoveCollectionViewCellDelegate && [m_MoveCollectionViewCellDelegate respondsToSelector:@selector(GesturePressDelegate:)]) {
[m_MoveCollectionViewCellDelegate GesturePressDelegate:gestureRecognizer];
}
}
這是cell的全部代碼。踱卵。据过。妒挎。
接下來(lái)去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
懶加載初始化個(gè)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];
}
這樣至少能夠顯示出來(lái)colloctionview了;
最后要實(shí)現(xiàn)的就是拖曳這一個(gè)動(dòng)作了
-(void)GesturePressDelegate:(UIGestureRecognizer *)gestureRecognizer
{
if ([[[UIDevice currentDevice] systemVersion] floatValue] >9) {
switch (gestureRecognizer.state) {
case UIGestureRecognizerStateBegan:{
//判斷手勢(shì)落點(diǎn)位置是否在路徑上
NSIndexPath *indexPath = [MJColloctionView indexPathForItemAtPoint:[gestureRecognizer locationInView:self.MJColloctionView]];
if (indexPath == nil) {
break;
}
//在路徑上則開(kāi)始移動(dòng)該路徑上的cell
[MJColloctionView beginInteractiveMovementForItemAtIndexPath:indexPath];
}
break;
case UIGestureRecognizerStateChanged:
//移動(dòng)過(guò)程當(dāng)中隨時(shí)更新cell位置
[MJColloctionView updateInteractiveMovementTargetPosition:[gestureRecognizer locationInView:self.MJColloctionView]];
break;
case UIGestureRecognizerStateEnded:
//移動(dòng)結(jié)束后關(guān)閉cell移動(dòng)
[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)
{
//獲取移動(dòng)量
CGFloat tranX = [gestureRecognizer locationOfTouch:0 inView:MJColloctionView].x - startPoint.x;
CGFloat tranY = [gestureRecognizer locationOfTouch:0 inView:MJColloctionView].y - startPoint.y;
//進(jìn)行移動(dòng)
_shotView.center = CGPointApplyAffineTransform(_shotView.center, CGAffineTransformMakeTranslation(tranX, tranY));
//更新初始位置
startPoint = [gestureRecognizer locationOfTouch:0 inView:MJColloctionView];
for (UICollectionViewCell *cellVisible in [MJColloctionView visibleCells])
{
//移動(dòng)的截圖與目標(biāo)cell的center直線距離
CGFloat space = sqrtf(pow(_shotView.center.x - cellVisible.center.x, 2) + powf(_shotView.center.y - cellVisible.center.y, 2));
//判斷是否替換位置庸队,通過(guò)直接距離與重合程度
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++)
{
//移動(dòng)數(shù)據(jù)源位置
[_arr exchangeObjectAtIndex:i withObjectAtIndex:i+1];
}
}else
{
for(NSInteger i = _indexPath.item; i <_nextIndexPath.item;i--)
{
//移動(dòng)數(shù)據(jù)源位置
[_arr exchangeObjectAtIndex:i withObjectAtIndex:i-1];
}
}
//移動(dòng)視圖cell位置
[MJColloctionView moveItemAtIndexPath:_indexPath toIndexPath:_nextIndexPath];
//更新移動(dòng)視圖的數(shù)據(jù)
_indexPath = _nextIndexPath;
break;
}
}
}else if (gestureRecognizer.state == UIGestureRecognizerStateEnded)
{
[_shotView removeFromSuperview];
[_originalCell setHidden:NO];
}
}
}
viewDidLoad加下數(shù)據(jù)
- (void)viewDidLoad {
[super viewDidLoad];
_arr = [[NSMutableArray alloc]initWithArray:[NSArray arrayWithObjects:@"我",@"的",@"背",@"脊",@"如",@"荒",@"丘",@",",@"而",@"你",@"卻",@"微",@"笑",@"擺",@"手",@",",@"把",@"它",@"當(dāng)",@"成",@"整",@"個(gè)",@"宇",@"宙", nil]];
[self.view addSubview:self.MJColloctionView];
// Do any additional setup after loading the view, typically from a nib.
}
就醬..................QAQ