【Objective-C】世界で一番簡単にUICollectionViewの並び替えを実行する書き方【Xcode10.2対応】
こういう人に向けて発信しています。
・CollectionViewをアニメーション込みで並び替えてたい人
・並び替える際にCollectionViewの範囲からははみ出して欲しくない人
・Objective-C中級者
アプリイメージ図
構成
・ViewController.h/m/xib
・CustomCell.h/m/xib
ViewController.h/m
//hファイル
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@end
//mファイル
#import "ViewController.h"
#import "CustomCell.h"
@interface ViewController ()<UICollectionViewDelegate,UICollectionViewDataSource>
@property (nonatomic) UICollectionView *collectionView;
@property (nonatomic) NSMutableArray *comboArray; //今回表示している配列(ダミーデータ入れます)
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.comboArray = @[@"ライオン",@"トラ",@"チーター",@"サイ",@"ゴリラ",@"ゾウ",@"クワガタ",@"カマキリ",@"バッタ",@"シャチ",@"ウナギ",@"タコ"].mutableCopy;
[self setCollectionView];
self.collectionView.dataSource = self;
self.collectionView.delegate = self;
UINib *nib = [UINib nibWithNibName:@"CustomCell" bundle:nil];
[self.collectionView registerNib:nib forCellWithReuseIdentifier:@"CustomCell"];
}
-(void)setCollectionView{
CGRect rect = CGRectMake(0, self.view.bounds.size.height/2, self.view.bounds.size.width, 120);
self.collectionView = [[UICollectionView alloc]initWithFrame:rect collectionViewLayout:[self collectionBrank]];
self.collectionView.backgroundColor = [UIColor whiteColor];
self.collectionView.bounces = NO;
[self.view addSubview:self.collectionView];
//ジェスチャーを設定
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongGesture:)];
//長押しのジェスチャーが動作するまでの時間(1.0などにすると1秒間長押ししないと呼び出されなくなる。)
longPress.minimumPressDuration = 0.3;
//ジェスチャーをcollectionViewに適用した。
[self.collectionView addGestureRecognizer:longPress];
}
-(void)handleLongGesture:(UILongPressGestureRecognizer *)gestureRecognizer{
// UILongPressGestureRecognizerからlocationInView:を使ってタップした場所のCGPointを取得する
CGPoint selectedCellPoint = [gestureRecognizer locationInView:self.collectionView];
// 取得したCGPointを利用して、indexPathForRowAtPoint:でタップした場所のNSIndexPathを取得する
NSIndexPath *selectedCell = [self.collectionView indexPathForItemAtPoint:selectedCellPoint];
switch (gestureRecognizer.state) {
case UIGestureRecognizerStateBegan:
//移動しはじめた初回1回のみ通る。
[self.collectionView beginInteractiveMovementForItemAtIndexPath:selectedCell];
break;
case UIGestureRecognizerStateChanged:
//移動し続ける間、通り続ける。
selectedCellPoint.y = self.collectionView.bounds.size.height/2; //スクロールビューの高さの中心にしか移動しないように
[self.collectionView updateInteractiveMovementTargetPosition:selectedCellPoint];
break;
case UIGestureRecognizerStateEnded:
[self.collectionView endInteractiveMovement];
break;
default:
[self.collectionView cancelInteractiveMovement];
break;
}
}
#pragma mark collectionView load
//collectionViewのレイアウトの諸設定を行う。
- (UICollectionViewFlowLayout *)collectionBrank{
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc]init]; //CollectionViewのレイアウトに関するクラスを初期化する
layout.sectionInset = UIEdgeInsetsMake(10, 10, 10, 10); //itemの余白をセットする。 上、左、下、右の順番
layout.scrollDirection = UICollectionViewScrollDirectionHorizontal; //横向きにスクロールできるようにする
return layout;
}
#pragma mark collectionView DataSource
//セクションの数を決める(itemではない)
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 1;
}
//itemの数を決める
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return self.comboArray.count;
}
//itemの中身を返す。
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
//カスタムセルの場合
CustomCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"CustomCell" forIndexPath:indexPath];
cell.cellLabel.text = self.comboArray[indexPath.row];
return cell;
}
//正常に移動された時のみ動作する(弾き出したりしても動作しない)
- (void)collectionView:(UICollectionView *)collectionView moveItemAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath{
NSLog(@"sourceIndexPath_このセルは%ld番目のセルになります!", (long)sourceIndexPath.row);
NSLog(@"destinationIndexPathこのセルは%ld番目のセルになります!", (long)destinationIndexPath.row);
NSString *targetString = self.comboArray[sourceIndexPath.row];
[self.comboArray removeObject:targetString];
[self.comboArray insertObject:targetString atIndex:destinationIndexPath.row]; //入れ替えではうまくいかなった
}
//itemのサイズを返す
- (CGSize)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout*)collectionViewLayout
sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
return CGSizeMake(100, 100);
}
@end