-
Notifications
You must be signed in to change notification settings - Fork 5
/
README.md~acab289c83c4001af8dcc23dcbf3b1f3c87a8438
201 lines (163 loc) · 6.84 KB
/
README.md~acab289c83c4001af8dcc23dcbf3b1f3c87a8438
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
# MoveAndDelete
iOS开发:UICollectionView长按移动、添加、删除(仿支付宝首页中的全部功能)
![效果图](http://upload-images.jianshu.io/upload_images/1840399-3963fd46ca66b073.gif?imageMogr2/auto-orient/strip)
UICollectionView添加手势,可以使cell移动、添加、删除,这种功能网上也有一大堆的资料可供查看,本文没有做封装,提供一个思路给读者;封装的再好,不符合自己的业务,还是需要修改的;
仿支付宝的效果,你可以打开支付宝,首页中有个全部功能,点击进去,第一个分区的cell是可以移动,第一个分区可以添加,可以删除;后面的分区不可以添加,也不能够删除和移动,如果第一个分区已经有了,下面的就是一个`✔️`号,如果没有,则显示`+`号;第一个分区永远都是`-`号,表示只能删除;
首先创建一个继承与`UICollectionViewFlowLayout`的类:.h中的代码
```
#import <UIKit/UIKit.h>
@protocol SYLifeManagerDelegate <NSObject>
/**
* 改变编辑状态
*/
- (void)didChangeEditState:(BOOL)inEditState;
/**
* 更新数据源
*/
- (void)moveItemAtIndexPath:(NSIndexPath *)formPath toIndexPath:(NSIndexPath *)toPath;
@end
@interface SYLifeManagerLayout : UICollectionViewFlowLayout
@property (nonatomic, assign) BOOL inEditState;
@property (nonatomic, assign) id<SYLifeManagerDelegate> delegate;
@end
```
#####.m中的代码:
```
#import "SYLifeManagerLayout.h"
#import "SYLifeManagerCell.h"
#import "SYLifeManagerModel.h"
#import "Header.h"
@interface SYLifeManagerLayout ()<UIGestureRecognizerDelegate>
@property (nonatomic, strong) UILongPressGestureRecognizer *longGesture;
@property (nonatomic, strong) NSIndexPath *currentIndexPath; //当前indexPath
@property (nonatomic, assign) CGPoint movePoint; //移动的中心点
@property (nonatomic, strong) UIView *moveView; //移动的视图
@end
@implementation SYLifeManagerLayout
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
[self configureObserver];
}
return self;
}
- (instancetype)init
{
self = [super init];
if (self) {
[self configureObserver];
}
return self;
}
#pragma mark - 添加观察者
- (void)configureObserver
{
[self addObserver:self forKeyPath:@"collectionView" options:NSKeyValueObservingOptionNew context:nil];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
{
if ([keyPath isEqualToString:@"collectionView"]) {
[self setUpGestureRecognizers];
} else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
#pragma mark - 长按手势
- (void)setUpGestureRecognizers
{
if (self.collectionView == nil) {
return;
}
[self.collectionView addGestureRecognizer:self.longGesture];
}
#pragma mark - 手势动画
- (void)longGesture:(UILongPressGestureRecognizer *)gesture
{
if (!self.inEditState) {
[self setInEditState:YES];
}
switch (gesture.state) {
case UIGestureRecognizerStateBegan: {
CGPoint location = [gesture locationInView:self.collectionView];
NSIndexPath *indexPath = [self.collectionView indexPathForItemAtPoint:location];
//如果indexPath为空,不做任何操作
if (indexPath == nil || indexPath.section != 0) return;
self.currentIndexPath = indexPath;
UICollectionViewCell *targetCell = [self.collectionView cellForItemAtIndexPath:self.currentIndexPath];
//得到当前cell的映射(截图)
self.moveView = [targetCell snapshotViewAfterScreenUpdates:YES];
self.moveView.layer.borderWidth = 0.3;
self.moveView.layer.borderColor = [UIColor sy_grayColor].CGColor;
[self.collectionView addSubview:self.moveView];
targetCell.hidden = YES;
self.moveView.transform = CGAffineTransformMakeScale(1.1, 1.1);
self.moveView.center = location;
}
break;
case UIGestureRecognizerStateChanged: {
CGPoint point = [gesture locationInView:self.collectionView];
//更新cell的位置
self.moveView.center = point;
NSIndexPath *indexPath = [self.collectionView indexPathForItemAtPoint:point];
if (indexPath == nil) return;
if (indexPath.section == self.currentIndexPath.section && indexPath.section == 0) {
[self.collectionView moveItemAtIndexPath:self.currentIndexPath toIndexPath:indexPath];
//使用代理方法更新数据源
if ([self.delegate respondsToSelector:@selector(moveItemAtIndexPath:toIndexPath:)]) {
[self.delegate moveItemAtIndexPath:self.currentIndexPath toIndexPath:indexPath];
}
self.currentIndexPath = indexPath;
}
}
break;
case UIGestureRecognizerStateEnded: {
UICollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:self.currentIndexPath];
[UIView animateWithDuration:0.25 animations:^{
self.moveView.center = cell.center;
} completion:^(BOOL finished) {
[self.moveView removeFromSuperview];
cell.hidden = NO;
self.moveView = nil;
self.currentIndexPath = nil;
[self.collectionView reloadData];
}];
}
break;
default:
break;
}
}
#pragma mark - 处于编辑状态
- (void)setInEditState:(BOOL)inEditState
{
if (_inEditState != inEditState) {
if (_delegate && [_delegate respondsToSelector:@selector(didChangeEditState:)]) {
[_delegate didChangeEditState:inEditState];
}
}
_inEditState = inEditState;
}
#pragma mark - 移除观察者
- (void)dealloc
{
[self removeObserver:self forKeyPath:@"collectionView"];
}
#pragma mark - 手势
- (UILongPressGestureRecognizer *)longGesture
{
if (!_longGesture) {
_longGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longGesture:)];
_longGesture.minimumPressDuration = 0.5f; //时间长短
_longGesture.delegate = self;
}
return _longGesture;
}
@end
```
限于文章篇幅长度,有需要的可以移步[demo](https://github.com/FirstDKS521/MoveAndDelete)
`SYLifeManagerCell`创建的cell,这个就不用多讲了,一般都是一张图片和描述文案
`SYLifeManagerModel`创建的model
`SYLifeManagerHeaderView`是创建的区头视图,为了显示分区标题
`SYLIfeManagerFooterView`是区尾视图,主要是为了实现分割线
[Demo的Github地址](https://github.com/FirstDKS521/MoveAndDelete),如果有问题或者好的建议,希望留言,欢迎交流!