iOS之UICollectionView的Item长按后抖动并且可移动效果

      前段时间由于公司需求,恰好需要做一个CollectionView的Item长按后抖动并且可移动效果。但由于一些原因,当时并没有来得及去处理,所以一直心有遗憾。目前市场上此功能并不少见,而且在github上也有一些类似的开源代码,所以其实总结来说:首先并不能作为一个功能难点,只能说是兴趣至此;其次也是真心希望能帮助一些我能帮助的人,以及希望大家能给些建议。都说不想当将军的士兵不是好士兵,所以我觉得,不能溜溜的马始终都是骡子...嘿嘿...回归正题...(可以复制此链接浏览器下载demo  http://git.oschina.net/JHissuperman/CollectionView)

1.首先是UICollectionView的创建:

//创建一个layout布局类

UICollectionViewFlowLayout* layout = [[UICollectionViewFlowLayout alloc]init];

//设置布局方向为垂直流布局

layout.scrollDirection = UICollectionViewScrollDirectionVertical;

//设置每个item的大小为127.5*127.5

layout.itemSize = CGSizeMake(114*kWidth/750.00, 114*kWidth/750.00);

//整体view据上左下右距离

layout.sectionInset = UIEdgeInsetsMake(48*kWidth/750.00, 48*kWidth/750.00, 48*kWidth/750.00,48*kWidth/750.00);

//每个item上下距离

layout.minimumLineSpacing = 90*kWidth/750.00;

//每个item左右距离

layout.minimumInteritemSpacing = 66*kWidth/750.00;

//创建collectionView 通过一个布局策略layout来创建

_vibrate = [[UICollectionView alloc]initWithFrame:CGRectMake(0, 0*kWidth/750.00, kWidth, kHeight) collectionViewLayout:layout];

_vibrate.delegate = self;

_vibrate.dataSource = self;

_vibrate.backgroundColor = [UIColor lightGrayColor];

_vibrate.showsHorizontalScrollIndicator = NO;

_vibrate.showsVerticalScrollIndicator = NO;

_vibrate.userInteractionEnabled = YES;

//注册item类型 这里使用系统的类型

[_vibrate registerClass:[VibrateCollectionViewCell class] forCellWithReuseIdentifier:@"vibrate"];

[self.view addSubview:_vibrate];

2.然后实现collectionview的代理方法:

//返回分区个数

-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{

return 1;

}

//返回每个分区的item个数

-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{

return _collectionArr.count;

}

//返回每个item

-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{

VibrateCollectionViewCell * cell  = [collectionView dequeueReusableCellWithReuseIdentifier:@"vibrate" forIndexPath:indexPath];

//    [cell sizeToFit];

if(!cell){

NSLog(@"-----------");

}

NSInteger num = indexPath.row;

cell.nameLable.text = _collectionArr[num];

cell.headImageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"00%@",_collectionArr[num]]];

if(_isBegin == YES ){

[self starLongPress:cell];

}

return cell;

}

3.添加手势

3.1  抖动手势的添加

- (void)addRecognize{

//添加长按抖动手势

if(!_recognize){

_recognize = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];

}

//长按响应时间

_recognize.minimumPressDuration = 1;

[_vibrate addGestureRecognizer:_recognize];

}

- (void)longPress:(UILongPressGestureRecognizer *)longGesture {

//判断手势状态

switch (longGesture.state) {

case UIGestureRecognizerStateBegan:{

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

NSIndexPath *indexPath = [self.vibrate indexPathForItemAtPoint:[longGesture locationInView:self.vibrate]];

if (indexPath.row >= 0) {//第一个不可移动  个人限制

_isBegin = YES;

[_vibrate removeGestureRecognizer:_recognize];

[self addLongGesture];

[self addSureButton];

[_vibrate reloadData];

NSLog(@"1");

}else{

break;

}

}

break;

case UIGestureRecognizerStateChanged:{

NSLog(@"2");

break;

}

case UIGestureRecognizerStateEnded:

NSLog(@"3");

break;

default:

NSLog(@"4");

break;

}

}

//开始抖动

- (void)starLongPress:(VibrateCollectionViewCell*)cell{

CABasicAnimation *animation = (CABasicAnimation *)[cell.layer animationForKey:@"rotation"];

if (animation == nil) {

[self shakeImage:cell];

}else {

[self resume:cell];

}

}

//这个参数的理解比较复杂,我的理解是所在layer的时间与父layer的时间的相对速度,为1时两者速度一样,为2那么父layer过了一秒,而所在layer过了两秒(进行两秒动画),为0则静止。

- (void)pause:(VibrateCollectionViewCell*)cell {

cell.layer.speed = 0.0;

}

- (void)resume:(VibrateCollectionViewCell*)cell {

cell.layer.speed = 1.0;

}

- (void)shakeImage:(VibrateCollectionViewCell*)cell {

//创建动画对象,绕Z轴旋转

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];

//设置属性,周期时长

[animation setDuration:0.08];

//抖动角度

animation.fromValue = @(-M_1_PI/2);

animation.toValue = @(M_1_PI/2);

//重复次数,无限大

animation.repeatCount = HUGE_VAL;

//恢复原样

animation.autoreverses = YES;

//锚点设置为图片中心,绕中心抖动

cell.layer.anchorPoint = CGPointMake(0.5, 0.5);

[cell.layer addAnimation:animation forKey:@"rotation"];

}

3.2 移动手势的添加

- (void)addLongGesture{

//此处给其增加长按手势,用此手势触发cell移动效果

if(!_longGesture){

_longGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handlelongGesture:)];

}

_longGesture.minimumPressDuration = 0;

[_vibrate addGestureRecognizer:_longGesture];

}

//监听手势,并设置其允许移动cell和交换资源

- (void)handlelongGesture:(UILongPressGestureRecognizer *)longGesture {

//判断手势状态

switch (longGesture.state) {

case UIGestureRecognizerStateBegan:{

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

NSIndexPath *indexPath = [self.vibrate indexPathForItemAtPoint:[longGesture locationInView:self.vibrate]];

if (indexPath.row > 0) {//第一个不可移动  个人限制

[_vibrate beginInteractiveMovementForItemAtIndexPath:indexPath];

}else{

break;

}

}

break;

case UIGestureRecognizerStateChanged:{

NSIndexPath* indexPath = [_vibrate indexPathForItemAtPoint:[longGesture locationInView:_vibrate]];

if(indexPath.row<1){

break;//第一个不可移动  个人限制

}

//移动过程当中随时更新cell位置

[_vibrate updateInteractiveMovementTargetPosition:[longGesture locationInView:_vibrate]];

break;

}

case UIGestureRecognizerStateEnded:

//移动结束后关闭cell移动

[_vibrate endInteractiveMovement];

break;

default:

[_vibrate endInteractiveMovement];

//            [_vibrate cancelInteractiveMovement];

break;

}

}

- (BOOL)collectionView:(UICollectionView *)collectionView canMoveItemAtIndexPath:(NSIndexPath *)indexPath{

return YES;

}

- (void)collectionView:(UICollectionView *)collectionView moveItemAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath*)destinationIndexPath {

//取出源item数据

id objc = [_collectionArr objectAtIndex:sourceIndexPath.item];

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

[_collectionArr removeObject:objc];

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

[_collectionArr insertObject:objc atIndex:destinationIndexPath.item];

//    [_vibrate reloadData];

}

具体效果  可以复制此链接浏览器下载demo  http://git.oschina.net/JHissuperman/CollectionView

希望能帮助到一些人,也希望大家能够指正一些问题。请大家多多留言发表意见。

(开源中国http://my.oschina.net/JHissuperman/blog/745064)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容