廢話不多說直接上代碼了,其核心實現(xiàn)代碼就是在-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
方法中的代碼
#import "MyChannelView.h"http://本類
#import "MyChannelCollectionViewCell.h"http:// 自定義cell
#define MyChannelCollectionViewCellID @"MyChannelCollectionViewCellID"
@interface MyChannelView ()<UICollectionViewDelegate,UICollectionViewDataSource, UICollectionViewDelegateFlowLayout>
@property (nonatomic,strong) UICollectionView *myChannelCollectionView;
@property (nonatomic,strong) NSMutableArray *selectedArray;// 0區(qū)數(shù)據(jù)源
@property (nonatomic,strong) NSMutableArray *deselectedArray;// 1區(qū)數(shù)據(jù)源
@property (nonatomic,strong) NSArray *allArray;//總數(shù)據(jù)源
@end
@implementation MyChannelView
-(instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.selectedArray = [NSMutableArray arrayWithArray:@[@"1", @"2", @"3", @"4", @"5", @"6", @"7", @"8", @"9", @"10"]];
self.deselectedArray = [NSMutableArray arrayWithArray:@[@"一", @"二", @"三", @"四", @"五", @"六", @"七", @"八", @"九", @"十"]];
self.allArray = @[self.selectedArray, self.deselectedArray];
UICollectionViewFlowLayout * layout = [[UICollectionViewFlowLayout alloc] init];
layout.minimumLineSpacing = 5;
layout.minimumInteritemSpacing = 5;
layout.scrollDirection = UICollectionViewScrollDirectionVertical;
self.myChannelCollectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 44, frame.size.width, frame.size.height-44) collectionViewLayout:layout];
self.myChannelCollectionView.delegate = self;
self.myChannelCollectionView.dataSource = self;
self.myChannelCollectionView.backgroundColor = [UIColor whiteColor];
[self addSubview:self.myChannelCollectionView];
[self.myChannelCollectionView registerClass:[MyChannelCollectionViewCell class] forCellWithReuseIdentifier:MyChannelCollectionViewCellID];
}
return self;
}
// delegate/dateSource method
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return self.allArray.count;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
switch (section) {
case 0:
return self.selectedArray.count;
break;
default:
return self.deselectedArray.count;
break;
}
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
MyChannelCollectionViewCell * cell = [collectionView dequeueReusableCellWithReuseIdentifier:MyChannelCollectionViewCellID forIndexPath:indexPath];
[cell.titleButton setTitle:self.allArray[indexPath.section][indexPath.row] forState:(UIControlStateNormal)];// 我這里自定義cell中就一個button
return cell;
}
// 分組間上左下右間距
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
{
return UIEdgeInsetsMake(10, 10, 10, 10);
}
// cell size
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
return CGSizeMake(ceilf((kGScreenWidth-50)/4), 44);
}
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
// 這里是重點!
if (indexPath.section == 0) {
NSString * one = self.selectedArray[indexPath.row];
[self.selectedArray removeObject:one];
[self.deselectedArray insertObject:one atIndex:0];
self.allArray = @[self.selectedArray, self.deselectedArray];
// 在這里是當你點選某個cell后希望他去哪一區(qū)亿驾,則將其移除于本數(shù)據(jù)源同時加入到你希望他去的那個數(shù)據(jù)源即可嘹黔。然后調(diào)用下面的方法
[collectionView moveItemAtIndexPath:indexPath toIndexPath:[NSIndexPath indexPathForItem:0 inSection:1]];
// 在調(diào)用該方法前一定要先更改數(shù)據(jù)源!
}else{
NSString * one = self.deselectedArray[indexPath.row];
[self.deselectedArray removeObject:one];
[self.selectedArray addObject:one];
self.allArray = @[self.selectedArray, self.deselectedArray];
[collectionView moveItemAtIndexPath:indexPath toIndexPath:[NSIndexPath indexPathForItem:self.selectedArray.count-1 inSection:0]];
}
}
@end
讓我們看一下效果:
效果圖
以下是進階版:
#import "MyChannelView.h" // 本類
#import "MyChannelCollectionViewCell.h" // 自定義cell
#import "ChannelModel.h" //數(shù)據(jù)model類 里面只有兩個屬性:NSString *ID 莫瞬、 NSString *name;
#import "MyChannelHeaderView.h" // 自定義section頭視圖 該視圖包括三個控件儡蔓,UILabel *titleLabel(標題)、UILabel *detaileLabel(說明)疼邀、UIButton *editButton(編輯按鈕);
// 重用標識
#define MyChannelCollectionViewCellID @"MyChannelCollectionViewCellID"
#define HeaderViewID @"SectionHeaderID"
@interface MyChannelView ()<UICollectionViewDelegate,UICollectionViewDataSource, UICollectionViewDelegateFlowLayout>
{
BOOL isEdit; //記錄我的頻道是否處于編輯狀態(tài)
BOOL isChanged; //記錄cell 是否移動
}
@property (nonatomic,strong) UIButton *missButton; // 該button上放了一張“X”號圖片 為取消按鈕
@property (nonatomic,strong) UICollectionView *myChannelCollectionView;
@property (nonatomic,strong) NSArray *allArray;
@property (nonatomic,strong) NSMutableArray *selectedArray;
@property (nonatomic,strong) NSMutableArray *deselectedArray;
@property (nonatomic,strong) UIPanGestureRecognizer * panGestureRecognizer; // cell上的拖拽手勢
@property (nonatomic,strong) NSMutableArray *cellAttributesArray;//記錄所有cell的attributes
@property (nonatomic,strong) UICollectionViewLayoutAttributes *attributes_isChange; // 記錄cell拖拽手勢結(jié)束后應(yīng)該在的位置attributes(僅在section為0時cell間拖拽移動使用)
@end
@implementation MyChannelView
-(instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [UIColor whiteColor];
self.cellAttributesArray = [NSMutableArray array];
self.missButton = [UIButton new];
[self.missButton setImage:[UIImage imageNamed:@"missImage"] forState:(UIControlStateNormal)];
[self.missButton addTarget:self action:@selector(missButtonAction) forControlEvents:(UIControlEventTouchUpInside)];
[self addSubview:self.missButton];
isEdit = NO; //初始是不處于編輯狀態(tài)
UICollectionViewFlowLayout * layout = [[UICollectionViewFlowLayout alloc] init];
layout.minimumLineSpacing = 5;
layout.minimumInteritemSpacing = 5;
layout.scrollDirection = UICollectionViewScrollDirectionVertical;
self.myChannelCollectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 64, frame.size.width, frame.size.height-64) collectionViewLayout:layout];
self.myChannelCollectionView.delegate = self;
self.myChannelCollectionView.dataSource = self;
self.myChannelCollectionView.backgroundColor = [UIColor whiteColor];
[self addSubview:self.myChannelCollectionView];
[self.myChannelCollectionView registerClass:[MyChannelCollectionViewCell class] forCellWithReuseIdentifier:MyChannelCollectionViewCellID];
[self.myChannelCollectionView registerClass:[MyChannelHeaderView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:HeaderViewID];
[self requestForData]; // 加載數(shù)據(jù)
}
return self;
}
- (void)layoutSubviews
{
[self.missButton makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(@20);
make.right.equalTo(@-10);
make.width.equalTo(@44);
make.height.equalTo(@44);
}];
self.myChannelCollectionView.frame = CGRectMake(0, 64, self.frame.size.width, self.frame.size.height-64);// 這里是做了轉(zhuǎn)屏功能所以····
}
- (void)missButtonAction
{
[self removeFromSuperview];
}
// 我的頻道界面數(shù)據(jù)
- (void)requestForData
{// 這里是做的數(shù)據(jù)請求喂江,就省略了,見諒旁振。結(jié)果類似如下:
self.selectedArray = [NSMutableArray arrayWithArray:@[@"1", @"2", @"3", @"4", @"5", @"6", @"7", @"8", @"9", @"10"]];
self.deselectedArray = [NSMutableArray arrayWithArray:@[@"一", @"二", @"三", @"四", @"五", @"六", @"七", @"八", @"九", @"十"]];
self.allArray = @[self.selectedArray, self.deselectedArray];
[self.myChannelCollectionView reloadData];
// 不過演示中數(shù)組元素都是model
}
// delegate/dateSource method
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return self.allArray.count;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
switch (section) {
case 0:
return self.selectedArray.count;
break;
default:
return self.deselectedArray.count;
break;
}
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
MyChannelCollectionViewCell * cell = [collectionView dequeueReusableCellWithReuseIdentifier:MyChannelCollectionViewCellID forIndexPath:indexPath];
self.panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGestureRecognizerAction:)];
ChannelModel * model = self.allArray[indexPath.section][indexPath.row];
[cell.titleButton setTitle:model.name forState:(UIControlStateNormal)];
if (isEdit && indexPath.section == 0) {
cell.editedButton.hidden = NO;
[cell addGestureRecognizer:self.panGestureRecognizer];
}else{// 隱藏表示處于編輯狀態(tài)的按鈕并移除拖拽手勢
cell.editedButton.hidden = YES;
NSArray * gestureArray = [cell gestureRecognizers];
for (UIGestureRecognizer * gesture in gestureArray) {
if ([gesture isKindOfClass:[UIPanGestureRecognizer class]]) {
[cell removeGestureRecognizer:gesture];
}
}
}
return cell;
}
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{
UICollectionReusableView * headerView = nil;
if (kind == UICollectionElementKindSectionHeader) {
MyChannelHeaderView * channelHeaderView = (MyChannelHeaderView *)[collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:HeaderViewID forIndexPath:indexPath];
if (indexPath.section == 0) {
channelHeaderView.titleLabel.text = @"我的頻道";
if (isEdit) {
channelHeaderView.detaileLabel.hidden = NO;
}else{
channelHeaderView.detaileLabel.hidden = YES;
}
channelHeaderView.editButton.hidden = NO;
[channelHeaderView.editButton addTarget:self action:@selector(channelHeaderViewAction) forControlEvents:(UIControlEventTouchUpInside)];
MyindexPath = indexPath;
}else{
channelHeaderView.titleLabel.text = @"點擊添加頻道";
channelHeaderView.editButton.hidden = YES;
channelHeaderView.detaileLabel.hidden = YES;
}
headerView = (UICollectionReusableView *)channelHeaderView;
}
return headerView;
}
#pragma 編輯按鈕點擊事件
- (void)channelHeaderViewAction
{
isEdit = !isEdit;
[self.myChannelCollectionView reloadData];
}
// 分組間上左下右間距
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
{
return UIEdgeInsetsMake(10, 10, 10, 10);
}
// header size
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section
{
return CGSizeMake(kGScreenWidth, 44);
}
// cell size
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
return CGSizeMake(ceilf((kGScreenWidth-50)/4), 44);
}
//cell的點擊事件
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
MyChannelCollectionViewCell * cell = (MyChannelCollectionViewCell *)[collectionView cellForItemAtIndexPath:indexPath];
if (indexPath.section == 0) {
#pragma 當處于編輯狀態(tài)時點擊會使零區(qū)cell移動到一區(qū)获询,不處于編輯狀態(tài)則會觸發(fā)其他事件
if (isEdit) {
ChannelModel * one = self.selectedArray[indexPath.row];
[self.selectedArray removeObject:one];
[self.deselectedArray insertObject:one atIndex:0];
self.allArray = @[self.selectedArray, self.deselectedArray];
[self setAllArrayToDefault:self.allArray];
NSArray * gestureArray = [cell gestureRecognizers];
for (UIGestureRecognizer * gesture in gestureArray) {
if ([gesture isKindOfClass:[UIPanGestureRecognizer class]]) {
[cell removeGestureRecognizer:gesture];
}
}
[collectionView moveItemAtIndexPath:indexPath toIndexPath:[NSIndexPath indexPathForItem:0 inSection:1]];
cell.editedButton.hidden = YES;
}else{ // 觸發(fā)其他事件,e.g :跳轉(zhuǎn)到其他頁面等
}
}else{
#pragma 一區(qū)的cell只能點擊 不能拖拽拐袜,點擊后只會移動到零區(qū)同時添加拖拽手勢
ChannelModel * one = self.deselectedArray[indexPath.row];
[self.deselectedArray removeObject:one];
[self.selectedArray addObject:one];
self.allArray = @[self.selectedArray, self.deselectedArray];
[self setAllArrayToDefault:self.allArray];
[cell addGestureRecognizer:self.panGestureRecognizer];
[collectionView moveItemAtIndexPath:indexPath toIndexPath:[NSIndexPath indexPathForItem:self.selectedArray.count-1 inSection:0]];
if (isEdit) {
cell.editedButton.hidden = NO;
}else{
cell.editedButton.hidden = YES;
}
}
}
#pragma 拖拽手勢響應(yīng)事件
- (void)panGestureRecognizerAction:(UIPanGestureRecognizer *)sender
{
MyChannelCollectionViewCell *cell = (MyChannelCollectionViewCell *)sender.view;
NSIndexPath *cellIndexPath = [self.myChannelCollectionView indexPathForCell:cell];
//將拖拽的cell提于視圖最前面
[self.myChannelCollectionView bringSubviewToFront:cell];
// 手勢響應(yīng)的三個狀態(tài)
if (sender.state == UIGestureRecognizerStateBegan) {
[self.cellAttributesArray removeAllObjects];
for (int i = 0;i< self.allArray.count; i++) {
NSMutableArray * tempArray = [NSMutableArray array];
NSArray * countArray = self.allArray[i];
for (int j = 0; j < countArray.count; j++) {
#pragma 這里是獲取每一個cell的屬性集合(Attributes)吉嚣,并按區(qū)區(qū)分開。很重要蹬铺!
[tempArray addObject:[self.myChannelCollectionView layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:j inSection:i]]];
}
[self.cellAttributesArray addObject:tempArray];
}
}else if (sender.state == UIGestureRecognizerStateChanged){
cell.center = [sender locationInView:self.myChannelCollectionView]; // 讓cell時刻跟隨手勢移動
NSArray *tempArr = self.cellAttributesArray[0];
for (UICollectionViewLayoutAttributes *attributes in tempArr) {
#pragma 判斷Attributes集合中的元素的fram是否包含cell的center尝哆,同時不能使cell本身且分區(qū)必須為0 才能成功地移動換位置
if (CGRectContainsPoint(attributes.frame, cell.center) && cellIndexPath != attributes.indexPath && attributes.indexPath.section == 0) {
isChanged = YES; // 標識-cell已經(jīng)和其他cell換了位置
//對數(shù)組中存放的元素重新排序
ChannelModel * one = self.selectedArray[cellIndexPath.row];
[self.selectedArray removeObject:one];
[self.selectedArray insertObject:one atIndex:attributes.indexPath.row];
self.allArray = @[self.selectedArray, self.deselectedArray];
[self setAllArrayToDefault:self.allArray];
[self.myChannelCollectionView moveItemAtIndexPath:cellIndexPath toIndexPath:attributes.indexPath];
self.attributes_isChange = attributes; // 移動完成后記錄被替換的cell的屬性(用來矯正cell位置)
}
}
}else if (sender.state == UIGestureRecognizerStateEnded) {
if (!isChanged) { // 沒有換位置(這里有兩種情況1、拖拽到了一區(qū)甜攀;2秋泄、還在自己原來的位置上)
UICollectionViewLayoutAttributes *attributes_done;
for (NSArray *tempArr in self.cellAttributesArray) {
for (UICollectionViewLayoutAttributes *attributes in tempArr) {
if (CGRectContainsPoint(attributes.frame, [sender locationInView:self.myChannelCollectionView])) {
attributes_done = attributes;
}
}
}
if (attributes_done.indexPath.section == 1) {
ChannelModel * one = self.selectedArray[cellIndexPath.row];
[self.selectedArray removeObject:one];
[self.deselectedArray insertObject:one atIndex:0];
self.allArray = @[self.selectedArray, self.deselectedArray];
[self setAllArrayToDefault:self.allArray];
NSArray * gestureArray = [cell gestureRecognizers];
for (UIGestureRecognizer * gesture in gestureArray) {
if ([gesture isKindOfClass:[UIPanGestureRecognizer class]]) {
[cell removeGestureRecognizer:gesture];
}
}
cell.editedButton.hidden = YES;
[self.myChannelCollectionView moveItemAtIndexPath:cellIndexPath toIndexPath:[NSIndexPath indexPathForItem:0 inSection:1]];
}else{ // 位置未改變情況下位置矯正
cell.center = [self.myChannelCollectionView layoutAttributesForItemAtIndexPath:cellIndexPath].center;
}
}else{// 已經(jīng)移動后矯正位置
cell.center = self.attributes_isChange.center;
}
isChanged = NO;
}
}
@end
效果圖:(做的有點難看琐馆,大家將就~~)
進階版效果圖