iOS开发UICollectionView实现拖拽效果

2025-05-29 0 104

一.介绍

ios9提供api实现单元格排序功能,使用uicollectionview及其代理方法。ios9之后有自带方法可以实现该效果,只需添加长按手势,实现手势方法和调用ios9的api交换数据,ios9之前需要自己写方法实现这效果,除了要添加长按手势,这里还需要利用截图替换原理,手动计算移动位置来处理视图交换和数据交换。

二.方法和步骤

1.创建工程项目和视图控制器,如下图

iOS开发UICollectionView实现拖拽效果

2.声明对象和设置代理和数据源代理

?

1

2

3

4

5

6

7

8

9

10

11

12
@interface viewcontroller ()<uicollectionviewdelegate,uicollectionviewdatasource,uicollectionviewdelegateflowlayout>

@property (nonatomic, strong) nsmutablearray *dataarr;

@property (nonatomic, strong) uicollectionview *collectionview;

/**之前选中cell的nsindexpath*/

@property (nonatomic, strong) nsindexpath *oldindexpath;

/**单元格的截图*/

@property (nonatomic, strong) uiview *snapshotview;

/**之前选中cell的nsindexpath*/

@property (nonatomic, strong) nsindexpath *moveindexpath;

@end

3.初始化uicollectionview,并添加长按手势,在viewdidload中初始化

?

1

2

3

4

5

6

7

8

9

10

11

12

13
cgfloat screen_width = self.view.frame.size.width;

uicollectionviewflowlayout *flowlayout = [[uicollectionviewflowlayout alloc] init];

flowlayout.itemsize = cgsizemake((screen_width-40.0)/3, (screen_width-40.0)/3);

uicollectionview *collectionview = [[uicollectionview alloc] initwithframe:cgrectmake(0, 50.0, screen_width, (screen_width-40.0)/3+20.0) collectionviewlayout:flowlayout];

collectionview.datasource = self;

collectionview.delegate = self;

collectionview.backgroundcolor = [uicolor whitecolor];

[collectionview registerclass:[uicollectionviewcell class] forcellwithreuseidentifier:@"uicollectionviewcell"];

[self.view addsubview:self.collectionview = collectionview];

// 添加长按手势

uilongpressgesturerecognizer *longpress = [[uilongpressgesturerecognizer alloc] initwithtarget:self action:@selector(handlelonggesture:)];

[collectionview addgesturerecognizer:longpress];

4.实例化数据源,(50个随机颜色,透明度0.8),在viewdidload中初始化

?

1

2

3

4

5

6

7

8
self.dataarr = [[nsmutablearray alloc] init];

for (nsinteger index = 0; index < 50; index ++) {

cgfloat hue = (arc4random()%256/256.0); //0.0 到 1.0

cgfloat saturation = (arc4random()%128/256.0)+0.5; //0.5 到 1.0

cgfloat brightness = (arc4random()%128/256.0)+0.5; //0.5 到 1.0

uicolor *color = [uicolor colorwithhue:hue saturation:saturation brightness:brightness alpha:0.5];

[self.dataarr addobject:color];

}

5.实现uicollectionview的uicollectionviewdatasource的两个必须实现的方法

?

1

2

3

4

5

6

7

8

9

10

11

12
#pragma mark - uicollectionviewdatasource

- (nsinteger)collectionview:(uicollectionview *)collectionview numberofitemsinsection:(nsinteger)section

{

return self.dataarr.count;

}

- (uicollectionviewcell *)collectionview:(uicollectionview *)collectionview cellforitematindexpath:(nsindexpath *)indexpath

{

uicollectionviewcell *cell = [collectionview dequeuereusablecellwithreuseidentifier:@"uicollectionviewcell" forindexpath:indexpath];

cell.backgroundcolor = self.dataarr[indexpath.row];

return cell;

}

6.重点来了,实现长按手势方法

?

1

2

3

4

5

6

7

8

9
#pragma mark - 长按手势

- (void)handlelonggesture:(uilongpressgesturerecognizer *)longpress

{

if ([[[uidevice currentdevice] systemversion] floatvalue] < 9.0) {

[self action:longpress];

} else {

[self ios9_action:longpress];

}

}

7.ios9之后的实现

?

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
#pragma mark - ios9 之后的方法

- (bool)collectionview:(uicollectionview *)collectionview canmoveitematindexpath:(nsindexpath *)indexpath

{

// 返回yes允许row移动

return yes;

}

- (void)collectionview:(uicollectionview *)collectionview moveitematindexpath:(nsindexpath *)sourceindexpath toindexpath:(nsindexpath *)destinationindexpath

{

//取出移动row数据

id color = self.dataarr[sourceindexpath.row];

//从数据源中移除该数据

[self.dataarr removeobject:color];

//将数据插入到数据源中的目标位置

[self.dataarr insertobject:color atindex:destinationindexpath.row];

}

- (void)ios9_action:(uilongpressgesturerecognizer *)longpress

{

switch (longpress.state) {

case uigesturerecognizerstatebegan:

{ //手势开始

//判断手势落点位置是否在row上

nsindexpath *indexpath = [self.collectionview indexpathforitematpoint:[longpress locationinview:self.collectionview]];

if (indexpath == nil) {

break;

}

uicollectionviewcell *cell = [self.collectionview cellforitematindexpath:indexpath];

[self.view bringsubviewtofront:cell];

//ios9方法 移动cell

[self.collectionview begininteractivemovementforitematindexpath:indexpath];

}

break;

case uigesturerecognizerstatechanged:

{ // 手势改变

// ios9方法 移动过程中随时更新cell位置

[self.collectionview updateinteractivemovementtargetposition:[longpress locationinview:self.collectionview]];

}

break;

case uigesturerecognizerstateended:

{ // 手势结束

// ios9方法 移动结束后关闭cell移动

[self.collectionview endinteractivemovement];

}

break;

default: //手势其他状态

[self.collectionview cancelinteractivemovement];

break;

}

}

8.ios9之前的实现

?

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
#pragma mark - ios9 之前的方法

- (void)action:(uilongpressgesturerecognizer *)longpress

{

switch (longpress.state) {

case uigesturerecognizerstatebegan:

{ // 手势开始

//判断手势落点位置是否在row上

nsindexpath *indexpath = [self.collectionview indexpathforitematpoint:[longpress locationinview:self.collectionview]];

self.oldindexpath = indexpath;

if (indexpath == nil) {

break;

}

uicollectionviewcell *cell = [self.collectionview cellforitematindexpath:indexpath];

// 使用系统的截图功能,得到cell的截图视图

uiview *snapshotview = [cell snapshotviewafterscreenupdates:no];

snapshotview.frame = cell.frame;

[self.view addsubview:self.snapshotview = snapshotview];

// 截图后隐藏当前cell

cell.hidden = yes;

cgpoint currentpoint = [longpress locationinview:self.collectionview];

[uiview animatewithduration:0.25 animations:^{

snapshotview.transform = cgaffinetransformmakescale(1.05, 1.05);

snapshotview.center = currentpoint;

}];

}

break;

case uigesturerecognizerstatechanged:

{ // 手势改变

//当前手指位置 截图视图位置随着手指移动而移动

cgpoint currentpoint = [longpress locationinview:self.collectionview];

self.snapshotview.center = currentpoint;

// 计算截图视图和哪个可见cell相交

for (uicollectionviewcell *cell in self.collectionview.visiblecells) {

// 当前隐藏的cell就不需要交换了,直接continue

if ([self.collectionview indexpathforcell:cell] == self.oldindexpath) {

continue;

}

// 计算中心距

cgfloat space = sqrtf(pow(self.snapshotview.center.x - cell.center.x, 2) + powf(self.snapshotview.center.y - cell.center.y, 2));

// 如果相交一半就移动

if (space <= self.snapshotview.bounds.size.width / 2) {

self.moveindexpath = [self.collectionview indexpathforcell:cell];

//移动 会调用willmovetoindexpath方法更新数据源

[self.collectionview moveitematindexpath:self.oldindexpath toindexpath:self.moveindexpath];

//设置移动后的起始indexpath

self.oldindexpath = self.moveindexpath;

break;

}

}

}

break;

default:

{ // 手势结束和其他状态

uicollectionviewcell *cell = [self.collectionview cellforitematindexpath:self.oldindexpath];

// 结束动画过程中停止交互,防止出问题

self.collectionview.userinteractionenabled = no;

// 给截图视图一个动画移动到隐藏cell的新位置

[uiview animatewithduration:0.25 animations:^{

self.snapshotview.center = cell.center;

self.snapshotview.transform = cgaffinetransformmakescale(1.0, 1.0);

} completion:^(bool finished) {

// 移除截图视图,显示隐藏的cell并开始交互

[self.snapshotview removefromsuperview];

cell.hidden = no;

self.collectionview.userinteractionenabled = yes;

}];

}

break;

}

}

三.ios9之后添加的api如下

?

1

2

3

4

5
// support for reordering

- (bool)begininteractivemovementforitematindexpath:(nsindexpath *)indexpath ns_available_ios(9_0); // returns no if reordering was prevented from beginning - otherwise yes

- (void)updateinteractivemovementtargetposition:(cgpoint)targetposition ns_available_ios(9_0);

- (void)endinteractivemovement ns_available_ios(9_0);

- (void)cancelinteractivemovement ns_available_ios(9_0);

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持快网idc。

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

快网idc优惠网 建站教程 iOS开发UICollectionView实现拖拽效果 https://www.kuaiidc.com/89245.html

相关文章

发表评论
暂无评论