Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/118.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 使用UICollectionView创建一组用户可以浏览的照片_Ios_Iphone_Objective C_Uicollectionview_Uicollectionviewlayout - Fatal编程技术网

Ios 使用UICollectionView创建一组用户可以浏览的照片

Ios 使用UICollectionView创建一组用户可以浏览的照片,ios,iphone,objective-c,uicollectionview,uicollectionviewlayout,Ios,Iphone,Objective C,Uicollectionview,Uicollectionviewlayout,我正在尝试使用UICollectionView创建一组照片,用户可以在其中将照片滑动到一边。拖动照片时,它会变小(到最小比例),后面的照片会放大到最大比例。此最大比例是前景照片的原始大小 当拖动前景照片的平移手势结束时,如果它是最小比例,它将被发送到堆栈的后面,否则,它将被设置动画,返回到屏幕的中心,并放大回其原始大小(以及后面不断增长的照片) 我希望你还和我在一起,哈哈 现在,假设正在拖动的照片处于其最小大小,我将删除UICollectionView的用户交互,再次将照片设置为屏幕中心,并将其

我正在尝试使用
UICollectionView
创建一组照片,用户可以在其中将照片滑动到一边。拖动照片时,它会变小(到最小比例),后面的照片会放大到最大比例。此最大比例是前景照片的原始大小

当拖动前景照片的平移手势结束时,如果它是最小比例,它将被发送到堆栈的后面,否则,它将被设置动画,返回到屏幕的中心,并放大回其原始大小(以及后面不断增长的照片)

我希望你还和我在一起,哈哈

现在,假设正在拖动的照片处于其最小大小,我将删除
UICollectionView
的用户交互,再次将照片设置为屏幕中心,并将其大小设置为与其余背景图像匹配的动画。然后我将单元格发送到
UICollectionView
s子视图的后面

一旦所有这些动画都发生了,我就会更新我的数据源(一组图像),将前面的照片添加到后面,然后删除前面的照片

然后,我更新
UICollectionView
。这包括一个批处理更新,我在0:0的
nsindepath
处删除该项,然后在
nsindepath
处插入一项([photo count]-1):0

当此批处理更新完成时,我重新加载我的
UICollectionView
(因为只有
NSIndexPath
0:0处的项具有平移手势),并将用户交互重新添加到
UICollectionView

我希望这是有道理的

注释

背景照片的大小为80%

前景照片的大小为100%

这是相对于适合iPhone屏幕的
UICollectionView
而言的

我的问题

我的代码似乎工作得很好。我的问题来自于当我将手指从屏幕上拿开(平移手势结束),照片的动画(将其居中到屏幕中心,并像其他背景照片一样调整大小)结束

拖出的照片会重新出现在屏幕上,从背景照片(80%)到前景照片(100%)的大小会逐渐消失。一旦发生这种情况,照片将按预期重新排序

有人知道为什么会这样吗

这是我的平移手势代码:

CGPoint touchTranslation = [gesture translationInView:self.view];

static CGPoint originalCenter;

DIGalleryCollectionViewLayout *galleryCollectionViewLayout = (DIGalleryCollectionViewLayout *)self.galleryCollectionView.collectionViewLayout;

if (gesture.state == UIGestureRecognizerStateBegan) {
    //
    //  Began.
    //
    originalCenter = gesture.view.center;
} else if (gesture.state == UIGestureRecognizerStateChanged) {
    //
    //  Changed.
    //
    CGPoint translate = [gesture translationInView:gesture.view.superview];

    touchTranslation = CGPointMake(originalCenter.x + translate.x, originalCenter.y + translate.y);
    [gesture.view setCenter:touchTranslation];

    CGPoint pointsPhotoIsMovedBy = CGPointMake(fabsf(fabsf(originalCenter.x) - fabsf(touchTranslation.x)),
                                               fabsf(fabsf(originalCenter.y) - fabsf(touchTranslation.y)));

    //  Update cells.
    //
    CGFloat currentIncrement = MAX(pointsPhotoIsMovedBy.x, pointsPhotoIsMovedBy.y);

    for (NSIndexPath *indexPath in self.galleryCollectionView.indexPathsForVisibleItems) {
        UICollectionViewCell *cell = [self.galleryCollectionView cellForItemAtIndexPath:indexPath];

        if ([indexPath isEqual:[NSIndexPath indexPathForItem:0 inSection:0]]) {
            //
            //      Front.
            //
            CGFloat frontScalePercent = MIN(GalleryCollectionViewLayoutFrontRatioDefault,
                                            MAX(GalleryViewFrontScaleMinimum, GalleryCollectionViewLayoutFrontRatioDefault - (currentIncrement / 250.0f)));

            [cell setTransform:CGAffineTransformMakeScale(frontScalePercent, frontScalePercent)];
        } else if ([indexPath isEqual:[NSIndexPath indexPathForItem:1 inSection:0]]) {
            //
            //      Next.
            //
            CGFloat nextScalePercent = MAX(GalleryCollectionViewLayoutBackRatioDefault,
                                           MIN(GalleryViewNextScaleMaximum, (currentIncrement / 150.0f)));

            [cell setTransform:CGAffineTransformMakeScale(nextScalePercent, nextScalePercent)];
        } else {
            //
            //      Background.
            //
            [cell setTransform:CGAffineTransformMakeScale(GalleryCollectionViewLayoutBackRatioDefault,
                                                          GalleryCollectionViewLayoutBackRatioDefault)];
        }
    }
} else if (gesture.state == UIGestureRecognizerStateEnded) {
    //
    //  Ended.
    //
    if (gesture.view.transform.a == GalleryViewFrontScaleMinimum) {
        //
        //  Next photo.
        //
        [self.galleryCollectionView setUserInteractionEnabled:NO];
        [self.galleryCollectionView sendSubviewToBack:gesture.view];

        [UIView animateWithDuration:0.3f
                         animations:^{
                             [gesture.view setCenter:self.galleryCollectionView.center];
                             [gesture.view setTransform:CGAffineTransformMakeScale(GalleryCollectionViewLayoutBackRatioDefault,
                                                                                   GalleryCollectionViewLayoutBackRatioDefault)];
                         }
                         completion:^(BOOL finished) {
                             //
                             //          Data source
                             //
                             NSMutableArray *photos = [self.photos mutableCopy];

                             [photos addObject:[photos objectAtIndex:0]];
                             [photos removeObjectAtIndex:0];

                             [self setPhotos:photos];

                             //          Contents
                             //
                             [self.galleryCollectionView performBatchUpdates:^{
                                 [self.galleryCollectionView deleteItemsAtIndexPaths:@[[NSIndexPath indexPathForItem:0 inSection:0]]];
                                 [self.galleryCollectionView insertItemsAtIndexPaths:@[[NSIndexPath indexPathForItem:(self.photos.count - 1) inSection:0]]];
                             } completion:^(BOOL finished) {
                                 [self.galleryCollectionView reloadData];

                                 [self.galleryCollectionView setUserInteractionEnabled:YES];
                             }];
                         }];
    } else {
        //
        //  Stay.
        //
        [UIView animateWithDuration:0.3f
                              delay:0.0f
                            options:UIViewAnimationOptionCurveEaseIn
                         animations:^{
                             //
                             // Front cell.
                             //
                             [gesture.view setCenter:self.galleryCollectionView.center];
                             [gesture.view setTransform:CGAffineTransformMakeScale(GalleryCollectionViewLayoutFrontRatioDefault,
                                                                                   GalleryCollectionViewLayoutFrontRatioDefault)];

                             // Next cell.
                             //
                             for (NSIndexPath *indexPath in self.galleryCollectionView.indexPathsForVisibleItems) {
                                 if ([indexPath isEqual:[NSIndexPath indexPathForItem:1 inSection:0]]) {
                                     //
                                     //      Next.
                                     //
                                     UICollectionViewCell *cell = [self.galleryCollectionView cellForItemAtIndexPath:indexPath];
                                     [cell setTransform:CGAffineTransformMakeScale(GalleryCollectionViewLayoutBackRatioDefault,
                                                                                   GalleryCollectionViewLayoutBackRatioDefault)];
                                 }
                             }
                         }
                         completion:^(BOOL finished) {
                             [galleryCollectionViewLayout setFrontRatio:GalleryCollectionViewLayoutFrontRatioDefault];
                             [galleryCollectionViewLayout setNextRatio:GalleryCollectionViewLayoutBackRatioDefault];
                             [galleryCollectionViewLayout invalidateLayout];
                         }];
    }
}
NSMutableDictionary *newLayoutInfo = [NSMutableDictionary dictionary];
NSMutableDictionary *cellLayoutInfo = [NSMutableDictionary dictionary];

NSIndexPath *indexPath;

for (NSInteger section = 0; section < [self.collectionView numberOfSections]; section++) {
    NSInteger itemCount = [self.collectionView numberOfItemsInSection:section];

    for (NSInteger item = 0; item < itemCount; item++) {
        indexPath = [NSIndexPath indexPathForItem:item inSection:section];

        UICollectionViewLayoutAttributes *itemAttributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];

        [itemAttributes setSize:[self sizeForPhotoAtIndexPath:indexPath inContainerOfSize:self.collectionView.bounds.size]];
        [itemAttributes setCenter:self.collectionView.center];

        //  Z Index.
        //
        NSInteger zIndex = itemCount - item;
        [itemAttributes setZIndex:zIndex];

        //  Scale cells based on z position.
        //
        if (zIndex == itemCount) {
            //
            //      Foreground.
            //
            [itemAttributes setTransform:CGAffineTransformMakeScale(self.frontRatio, self.frontRatio)];
        } else if (zIndex == itemCount - 1) {
            //
            //      Next.
            //
            [itemAttributes setTransform:CGAffineTransformMakeScale(self.nextRatio, self.nextRatio)];
        } else {
            //
            //      Background.
            //
            [itemAttributes setTransform:CGAffineTransformMakeScale(GalleryCollectionViewLayoutBackRatioDefault,
                                                                    GalleryCollectionViewLayoutBackRatioDefault)];
        }

        cellLayoutInfo[indexPath] = itemAttributes;
    }
}

newLayoutInfo[GalleryCollectionViewLayoutCellKind] = cellLayoutInfo;

self.layoutInfo = newLayoutInfo;
UIImage *photo = [[(DIGalleryViewController *)self.collectionView.delegate photos] objectAtIndex:indexPath.row];

CGSize size = CGSizeMake(photo.size.width, photo.size.height);

UIGraphicsBeginImageContext(containerSize);
[photo drawInRect:CGRectMake(0.0f, 0.0f, containerSize.width, containerSize.height)];
UIImage *resizedPhoto = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

CGFloat ratio = photo.size.width / resizedPhoto.size.width;

size = CGSizeMake(resizedPhoto.size.width, photo.size.height / ratio);

return size;
这是我的prepareLayout:集合视图布局的代码:

CGPoint touchTranslation = [gesture translationInView:self.view];

static CGPoint originalCenter;

DIGalleryCollectionViewLayout *galleryCollectionViewLayout = (DIGalleryCollectionViewLayout *)self.galleryCollectionView.collectionViewLayout;

if (gesture.state == UIGestureRecognizerStateBegan) {
    //
    //  Began.
    //
    originalCenter = gesture.view.center;
} else if (gesture.state == UIGestureRecognizerStateChanged) {
    //
    //  Changed.
    //
    CGPoint translate = [gesture translationInView:gesture.view.superview];

    touchTranslation = CGPointMake(originalCenter.x + translate.x, originalCenter.y + translate.y);
    [gesture.view setCenter:touchTranslation];

    CGPoint pointsPhotoIsMovedBy = CGPointMake(fabsf(fabsf(originalCenter.x) - fabsf(touchTranslation.x)),
                                               fabsf(fabsf(originalCenter.y) - fabsf(touchTranslation.y)));

    //  Update cells.
    //
    CGFloat currentIncrement = MAX(pointsPhotoIsMovedBy.x, pointsPhotoIsMovedBy.y);

    for (NSIndexPath *indexPath in self.galleryCollectionView.indexPathsForVisibleItems) {
        UICollectionViewCell *cell = [self.galleryCollectionView cellForItemAtIndexPath:indexPath];

        if ([indexPath isEqual:[NSIndexPath indexPathForItem:0 inSection:0]]) {
            //
            //      Front.
            //
            CGFloat frontScalePercent = MIN(GalleryCollectionViewLayoutFrontRatioDefault,
                                            MAX(GalleryViewFrontScaleMinimum, GalleryCollectionViewLayoutFrontRatioDefault - (currentIncrement / 250.0f)));

            [cell setTransform:CGAffineTransformMakeScale(frontScalePercent, frontScalePercent)];
        } else if ([indexPath isEqual:[NSIndexPath indexPathForItem:1 inSection:0]]) {
            //
            //      Next.
            //
            CGFloat nextScalePercent = MAX(GalleryCollectionViewLayoutBackRatioDefault,
                                           MIN(GalleryViewNextScaleMaximum, (currentIncrement / 150.0f)));

            [cell setTransform:CGAffineTransformMakeScale(nextScalePercent, nextScalePercent)];
        } else {
            //
            //      Background.
            //
            [cell setTransform:CGAffineTransformMakeScale(GalleryCollectionViewLayoutBackRatioDefault,
                                                          GalleryCollectionViewLayoutBackRatioDefault)];
        }
    }
} else if (gesture.state == UIGestureRecognizerStateEnded) {
    //
    //  Ended.
    //
    if (gesture.view.transform.a == GalleryViewFrontScaleMinimum) {
        //
        //  Next photo.
        //
        [self.galleryCollectionView setUserInteractionEnabled:NO];
        [self.galleryCollectionView sendSubviewToBack:gesture.view];

        [UIView animateWithDuration:0.3f
                         animations:^{
                             [gesture.view setCenter:self.galleryCollectionView.center];
                             [gesture.view setTransform:CGAffineTransformMakeScale(GalleryCollectionViewLayoutBackRatioDefault,
                                                                                   GalleryCollectionViewLayoutBackRatioDefault)];
                         }
                         completion:^(BOOL finished) {
                             //
                             //          Data source
                             //
                             NSMutableArray *photos = [self.photos mutableCopy];

                             [photos addObject:[photos objectAtIndex:0]];
                             [photos removeObjectAtIndex:0];

                             [self setPhotos:photos];

                             //          Contents
                             //
                             [self.galleryCollectionView performBatchUpdates:^{
                                 [self.galleryCollectionView deleteItemsAtIndexPaths:@[[NSIndexPath indexPathForItem:0 inSection:0]]];
                                 [self.galleryCollectionView insertItemsAtIndexPaths:@[[NSIndexPath indexPathForItem:(self.photos.count - 1) inSection:0]]];
                             } completion:^(BOOL finished) {
                                 [self.galleryCollectionView reloadData];

                                 [self.galleryCollectionView setUserInteractionEnabled:YES];
                             }];
                         }];
    } else {
        //
        //  Stay.
        //
        [UIView animateWithDuration:0.3f
                              delay:0.0f
                            options:UIViewAnimationOptionCurveEaseIn
                         animations:^{
                             //
                             // Front cell.
                             //
                             [gesture.view setCenter:self.galleryCollectionView.center];
                             [gesture.view setTransform:CGAffineTransformMakeScale(GalleryCollectionViewLayoutFrontRatioDefault,
                                                                                   GalleryCollectionViewLayoutFrontRatioDefault)];

                             // Next cell.
                             //
                             for (NSIndexPath *indexPath in self.galleryCollectionView.indexPathsForVisibleItems) {
                                 if ([indexPath isEqual:[NSIndexPath indexPathForItem:1 inSection:0]]) {
                                     //
                                     //      Next.
                                     //
                                     UICollectionViewCell *cell = [self.galleryCollectionView cellForItemAtIndexPath:indexPath];
                                     [cell setTransform:CGAffineTransformMakeScale(GalleryCollectionViewLayoutBackRatioDefault,
                                                                                   GalleryCollectionViewLayoutBackRatioDefault)];
                                 }
                             }
                         }
                         completion:^(BOOL finished) {
                             [galleryCollectionViewLayout setFrontRatio:GalleryCollectionViewLayoutFrontRatioDefault];
                             [galleryCollectionViewLayout setNextRatio:GalleryCollectionViewLayoutBackRatioDefault];
                             [galleryCollectionViewLayout invalidateLayout];
                         }];
    }
}
NSMutableDictionary *newLayoutInfo = [NSMutableDictionary dictionary];
NSMutableDictionary *cellLayoutInfo = [NSMutableDictionary dictionary];

NSIndexPath *indexPath;

for (NSInteger section = 0; section < [self.collectionView numberOfSections]; section++) {
    NSInteger itemCount = [self.collectionView numberOfItemsInSection:section];

    for (NSInteger item = 0; item < itemCount; item++) {
        indexPath = [NSIndexPath indexPathForItem:item inSection:section];

        UICollectionViewLayoutAttributes *itemAttributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];

        [itemAttributes setSize:[self sizeForPhotoAtIndexPath:indexPath inContainerOfSize:self.collectionView.bounds.size]];
        [itemAttributes setCenter:self.collectionView.center];

        //  Z Index.
        //
        NSInteger zIndex = itemCount - item;
        [itemAttributes setZIndex:zIndex];

        //  Scale cells based on z position.
        //
        if (zIndex == itemCount) {
            //
            //      Foreground.
            //
            [itemAttributes setTransform:CGAffineTransformMakeScale(self.frontRatio, self.frontRatio)];
        } else if (zIndex == itemCount - 1) {
            //
            //      Next.
            //
            [itemAttributes setTransform:CGAffineTransformMakeScale(self.nextRatio, self.nextRatio)];
        } else {
            //
            //      Background.
            //
            [itemAttributes setTransform:CGAffineTransformMakeScale(GalleryCollectionViewLayoutBackRatioDefault,
                                                                    GalleryCollectionViewLayoutBackRatioDefault)];
        }

        cellLayoutInfo[indexPath] = itemAttributes;
    }
}

newLayoutInfo[GalleryCollectionViewLayoutCellKind] = cellLayoutInfo;

self.layoutInfo = newLayoutInfo;
UIImage *photo = [[(DIGalleryViewController *)self.collectionView.delegate photos] objectAtIndex:indexPath.row];

CGSize size = CGSizeMake(photo.size.width, photo.size.height);

UIGraphicsBeginImageContext(containerSize);
[photo drawInRect:CGRectMake(0.0f, 0.0f, containerSize.width, containerSize.height)];
UIImage *resizedPhoto = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

CGFloat ratio = photo.size.width / resizedPhoto.size.width;

size = CGSizeMake(resizedPhoto.size.width, photo.size.height / ratio);

return size;

我还应该指出,在
setPhotos:
方法中,我没有在
UICollectionView
上调用
reloadData
,我的理解是问题来自
prepareLayout
。我认为在这种方法中发生的变换在某种程度上被重新应用了。我的新理论是基于这样一个事实:在平移手势中,单元格正在根据其
transform
属性调整大小,然而,在
prepareLayout
中,变换是基于
UICollectionViewLayoutAttribute