为了摇动单元格,我已经在每个单元格上添加了UILongPressGesture.当手势结束时,我已经添加了一个自定义动画.还在左上角添加了一个删除按钮.
长按手势代码:
declaration of variables CGPoint p; UILongPressGestureRecognizer *lpgr; NSIndexPath *gesture_indexPath;
添加手势到集合视图
lpgr
= [[UILongPressGestureRecognizer alloc]
initWithTarget:self action:@selector(handleLongPress:)];
lpgr.minimumPressDuration = .3; // To detect after how many seconds you want shake the cells
lpgr.delegate = self;
[self.collection_view addGestureRecognizer:lpgr];
lpgr.delaystouchesBegan = YES;
回调方法
-(void)handleLongPress:(UILongPressGestureRecognizer *)gestureRecognizer
{
if (gestureRecognizer.state != UIGestureRecognizerStateEnded)
{
return;
}
p = [gestureRecognizer locationInView:self.collection_view];
NSIndexPath *indexPath = [self.collection_view indexPathForItemAtPoint:p];
if (indexPath == nil)
{
NSLog(@"Couldn't find index path");
}
else
{
[[NSUserDefaults standardUserDefaults]setValue:@"yes" forKey:@"longpressed"];
[self.collection_view reloadData];
}
}
单元格在inde路径项
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"arr_album index row");
BlogalbumCell *cell;
static Nsstring *identifier = @"UserBlogalbum";
cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
UserAlbum *user_allbum=[arr_userAlbums objectAtIndex:indexPath.row];
cell.label_blog_name.text=user_allbum.album_name;
cell.image_blog_image.image = [UIImage imageNamed:@"more.png"];
[cell.image_blog_image setimageWithURL:[NSURL URLWithString:[IMAGE_BASE_URL stringByAppendingString:user_allbum.album_image]]];
if([[[NSUserDefaults standardUserDefaults]valueForKey:@"longpressed"] isEqualToString:@"yes"])
{
CABasicAnimation* anim = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
[anim setTovalue:[NSNumber numberWithFloat:0.0f]];
[anim setFromValue:[NSNumber numberWithDouble:M_PI/50]];
[anim setDuration:0.1];
[anim setRepeatCount:NSUIntegerMax];
[anim setAutoreverses:YES];
cell.layer.shouldRasterize = YES;
[cell.layer addAnimation:anim forKey:@"SpringboardShake"];
CGFloat delButtonSize = 20;
UIButton *delButton = [[UIButton alloc] initWithFrame:CGRectMake(0,delButtonSize,delButtonSize)];
delButton.center = CGPointMake(9,10);
delButton.backgroundColor = [UIColor clearColor];
[delButton setimage: [UIImage imageNamed:@"cross_30.png"] forState:UIControlStatenormal];
[cell addSubview:delButton];
[delButton addTarget:self action:@selector(deleteRecipe:) forControlEvents:UIControlEventTouchUpInside];
}
else if ([[[NSUserDefaults standardUserDefaults]valueForKey:@"singleTap"] isEqualToString:@"yes"])
{
for(UIView *subview in [cell subviews])
{
if([subview isKindOfClass:[UIButton class]])
{
[subview removeFromSuperview];
}
else
{
// Do nothing - not a UIButton or subclass instance
}
}
[cell.layer removeAllAnimations];
// _deleteButton.hidden = YES;
// [_deleteButton removeFromSuperview];
}
return cell;
}
在这里工作正常
为了移动单元格,我做了一个示例应用程序,其中我添加了UICollectionViewController&覆盖此方法
-(void)collectionView:(UICollectionView *)collectionView moveItemAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
{
NSLog(@"Move at index path called");
}
这也很好.它也使用长按手势&当手势被取消时,我可以移动细胞.但现在问题是在一个我可以移动单元格或动画他们.如果我添加我的自定义手势,那么我无法移动图像.请告诉我如何删除这个问题?
解决方法
编辑:这个问题可以分解成2个较小的子问题:
>如何动画细胞
>如何使用拖放重新排序单元格.
您应该将这两个解决方案组合到UICollectionView的子文件夹中,以获得您的主要解决方案.
如何动画细胞
要获得摆动动画,您需要添加2种不同的动画效果:
>垂直移动单元格,上下移动
>旋转单元格
>最后,为每个单元格添加一个随机的间隔时间,所以看起来单元格不能均匀地动画化
这是代码:
@interface DragDropCollectionView ()
@property (assign,nonatomic) BOOL isWiggling;
@end
@implementation DragDropCollectionView
//Start and Stop methods for wiggle
- (void) startWiggle {
for (UICollectionViewCell *cell in self.visibleCells) {
[self addWiggleAnimationToCell:cell];
}
self.isWiggling = true;
}
- (void)stopWiggle {
for (UICollectionViewCell *cell in self.visibleCells) {
[cell.layer removeAllAnimations];
}
self.isWiggling = false;
}
//- (UICollectionViewCell *)dequ
- (UICollectionViewCell *)dequeueReusableCellWithReuseIdentifier:(Nsstring *)identifier forIndexPath:(nonnull NSIndexPath *)indexPath{
UICollectionViewCell *cell = [super dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
if (self.isWiggling) {
[self addWiggleAnimationToCell:cell];
} else {
[cell.layer removeAllAnimations];
}
return [[UICollectionViewCell alloc] init];
}
//Animations
- (void)addWiggleAnimationToCell:(UICollectionViewCell *)cell {
[CATransaction begin];
[CATransaction setdisableActions:false];
[cell.layer addAnimation:[self rotationAnimation] forKey:@"rotation"];
[cell.layer addAnimation:[self bounceAnimation] forKey:@"bounce"];
[CATransaction commit];
}
- (CAKeyframeAnimation *)rotationAnimation {
CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation.z"];
CGFloat angle = 0.04;
NSTimeInterval duration = 0.1;
double variance = 0.025;
animation.values = @[@(angle),@(-1 * angle)];
animation.autoreverses = YES;
animation.duration = [self randomizeInterval:duration withVariance: variance];
animation.repeatCount = INFINITY;
return animation;
}
- (CAKeyframeAnimation *)bounceAnimation {
CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"transform.translation.y"];
CGFloat bounce = 3.0;
NSTimeInterval duration = 0.12;
double variance = 0.025;
animation.values = @[@(bounce),@(-1 * bounce)];
animation.autoreverses = YES;
animation.duration = [self randomizeInterval:duration withVariance: variance];
animation.repeatCount = INFINITY;
return animation;
}
- (NSTimeInterval)randomizeInterval:(NSTimeInterval)interval withVariance:(double)variance {
double randomDecimal = (arc4random() % 1000 - 500.0) / 500.0;
return interval + variance * randomDecimal;
}
如何使用拖放重新排序单元格
所以想法是这样的:你不是移动实际的单元格,而是移动一个UIImageView与单元格内容的UIImage.
算法或多或少是这样的.我把它分解成3个部分,手势识别器,改变和结束
gestureRecognizerBegan:
>当手势识别器开始时,确定长按确实在一个单元格上(而不是在空白的空间)
>获取单元格的UIImage(请参阅我的方法“getRasterizedImageOfCell”)
>隐藏单元格(即alpha = 0),创建具有单元格确切框架的UIImageView,以便用户不会意识到您实际上已隐藏单元格,并且实际上正在使用imageview.
gestureRecognizerChanged:
>更新UIImageView的中心,使其随手指移动.
>如果用户已经停止移动他的眼睛,即他将鼠标悬停在要替换的单元格上,那么现在需要交换单元格. (看看我的函数“shouldSwapCells”,这个方法返回一个bool是否单元格应该交换)
>将要拖动的单元格移动到新的indexPath. (看我的方法“swapDraggedCell”). UICollectionView有一个称为“moveItemAtIndexPath:toIndexPath”的内置方法,我不知道UITableView是否具有相同的东西
gestureRecognizerEnd:
>将UIImageView“放下”回到单元格
>将单元格alpha从0.0更改为1.0,并从视图中删除UIImageView.
这是代码:
@interface DragDropCollectionView ()
@property (strong,nonatomic) NSIndexPath *draggedCellIndexPath;
@property (strong,nonatomic) UIImageView *draggingImageView;
@property (assign,nonatomic) CGPoint touchOffsetFromCenterOfCell;
@property (strong,nonatomic) UILongPressGestureRecognizer *longPressRecognizer;
@end
@implementation DragDropCollectionView
- (void)handleLongPress:(UILongPressGestureRecognizer *)longPressRecognizer {
CGPoint touchLocation = [longPressRecognizer locationInView:self];
switch (longPressRecognizer.state) {
case UIGestureRecognizerStateBegan: {
self.draggedCellIndexPath = [self indexPathForItemAtPoint:touchLocation];
if (self.draggedCellIndexPath != nil) {
UICollectionViewCell *draggedCell = [self cellForItemAtIndexPath:self.draggedCellIndexPath];
self.draggingImageView = [[UIImageView alloc] initWithImage:[self rasterizedImagecopyOfCell:draggedCell]];
self.draggingImageView.center = draggedCell.center;
[self addSubview:self.draggingImageView];
draggedCell.alpha = 0.0;
self.touchOffsetFromCenterOfCell = CGPointMake(draggedCell.center.x - touchLocation.x,draggedCell.center.y - touchLocation.y);
[UIView animateWithDuration:0.4 animations:^{
self.draggingImageView.transform = CGAffineTransformMakeScale(1.3,1.3);
self.draggingImageView.alpha = 0.8;
}];
}
break;
}
case UIGestureRecognizerStateChanged: {
if (self.draggedCellIndexPath != nil) {
self.draggingImageView.center = CGPointMake(touchLocation.x + self.touchOffsetFromCenterOfCell.x,touchLocation.y + self.touchOffsetFromCenterOfCell.y);
}
float pingInterval = 0.3;
dispatch_after(dispatch_time(disPATCH_TIME_Now,(int64_t)(pingInterval * NSEC_PER_SEC)),dispatch_get_main_queue(),^{
NSIndexPath *newIndexPath = [self indexPathToSwapCellWithAtPrevIoUsTouchLocation:touchLocation];
if (newIndexPath) {
[self swapDraggedCellWithCellAtIndexPath:newIndexPath];
}
});
break;
}
case UIGestureRecognizerStateEnded: {
if (self.draggedCellIndexPath != nil ) {
UICollectionViewCell *draggedCell = [self cellForItemAtIndexPath:self.draggedCellIndexPath];
[UIView animateWithDuration:0.4 animations:^{
self.draggingImageView.transform = CGAffineTransformIdentity;
self.draggingImageView.alpha = 1.0;
if (draggedCell != nil) {
self.draggingImageView.center = draggedCell.center;
}
} completion:^(BOOL finished) {
[self.draggingImageView removeFromSuperview];
self.draggingImageView = nil;
if (draggedCell != nil) {
draggedCell.alpha = 1.0;
self.draggedCellIndexPath = nil;
}
}];
}
}
default:
break;
}
}
- (UIImage *)rasterizedImagecopyOfCell:(UICollectionViewCell *)cell {
UIGraphicsBeginImageContextWithOptions(cell.bounds.size,false,0.0);
[cell.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetimageFromCurrentimageContext();
return image;
}
- (NSIndexPath *)indexPathToSwapCellWithAtPrevIoUsTouchLocation:(CGPoint)prevIoUsTouchLocation {
CGPoint currentTouchLocation = [self.longPressRecognizer locationInView:self];
if (!isnan(currentTouchLocation.x) && !isnan(currentTouchLocation.y)) {
if ([self distanceBetweenPoints:currentTouchLocation secondPoint:prevIoUsTouchLocation] < 20.0) {
NSIndexPath *newIndexPath = [self indexPathForItemAtPoint:currentTouchLocation];
return newIndexPath;
}
}
return nil;
}
- (CGFloat)distanceBetweenPoints:(CGPoint)firstPoint secondPoint:(CGPoint)secondPoint {
CGFloat xdistance = firstPoint.x - secondPoint.x;
CGFloat ydistance = firstPoint.y - secondPoint.y;
return sqrtf(xdistance * xdistance + ydistance * ydistance);
}
- (void)swapDraggedCellWithCellAtIndexPath:(NSIndexPath *)newIndexPath {
[self moveItemAtIndexPath:self.draggedCellIndexPath toIndexPath:newIndexPath];
UICollectionViewCell *draggedCell = [self cellForItemAtIndexPath:newIndexPath];
draggedCell.alpha = 0.0;
self.draggedCellIndexPath = newIndexPath;
}
希望这可以帮助 :)