如何在 UICollectionViewCell 内缩放 UIScrollView?

Posted

技术标签:

【中文标题】如何在 UICollectionViewCell 内缩放 UIScrollView?【英文标题】:How to zoom a UIScrollView inside of a UICollectionViewCell? 【发布时间】:2013-06-06 11:07:32 【问题描述】:

我正在尝试在 UICollectionViewCell 中添加 UIScrollView。这个想法是您可以使用捏缩放UIScrollView(以及其中的图像),但滚动视图似乎不处理任何手势。我猜他们被UICollectionView 抓住了。

我已将UIScrollView 的委托设置为UICollectionViewCell,但没有调用任何委托方法。

编辑: 我用代码制作了一个 github repo(尽可能简化)。虽然只是几行代码,但我看不出我做错了什么。

EDIT2:找到答案后,我将修复添加到上述存储库中,希望其他人也觉得它有帮助:)

https://github.com/krummler/gallery-pinchzoom-example

【问题讨论】:

感谢您将更新的代码放入存储库。这对我很有用! 链接已损坏。请更新链接 【参考方案1】:

我刚刚在 iOS 9.3+ 上实现了 SWIFT 3,我所做的只是:

1.将图像视图放在滚动视图中

2。将滚动视图委托连接到 collectionview 单元类

3.在collectionview子类上实现下面的代码

class FullScreenImageTextDetailCollectionViewCell: UICollectionViewCell, UIScrollViewDelegate 

     @IBOutlet var scrollview: UIScrollView!
     @IBOutlet weak var backgroundImageView: UIImageView!

     override func awakeFromNib() 
         self.scrollview.minimumZoomScale = 0.5
         self.scrollview.maximumZoomScale = 3.5
         self.scrollview.delegate = self
     

     func viewForZooming(in scrollView: UIScrollView) -> UIView? 
         return self.backgroundImageView
     

不需要在父collectionview控制器上添加或删除手势识别器,就像一个魅力!

感谢之前的示例!

【讨论】:

很好的答案。将 viewForZooming 委托回调放在 cell 类中是关键。 您能否为此提供 .swift 和 .xib 文件。这似乎很简单,但我无法让它最终发挥作用。【参考方案2】:

您可能想尝试操作 UIGestureRecognizers 来做到这一点。在GalleryViewController

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

    GalleryImageCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"galleryImageCell" forIndexPath:indexPath];

    ImageContext *imageContext = [self.images objectAtIndex:indexPath.row];

    cell.imageContext = imageContext;
    [self.collectionView addGestureRecognizer:cell.scrollView.pinchGestureRecognizer];
    [self.collectionView addGestureRecognizer:cell.scrollView.panGestureRecognizer];

    return cell;

来自Apple's documentation on UIView:

将手势识别器附加到视图定义了所表示手势的范围,使其接收对该视图及其所有子视图进行命中测试的触摸。视图保留了手势识别器。

因此,您还需要确保在单元格不再显示时将其删除。

- (void)collectionView:(UICollectionView *)collectionView 
  didEndDisplayingCell:(UICollectionViewCell *)cell 
    forItemAtIndexPath:(NSIndexPath *)indexPath 

    // Get the cell instance and ...
    [self.collectionView removeGestureRecognizer:cell.scrollView.pinchGestureRecognizer];
    [self.collectionView removeGestureRecognizer:cell.scrollView.panGestureRecognizer];

由于您没有修改 UIGestureRecognizer 的委托,仅修改其范围,它仍将控制该单元格的滚动视图的缩放。

编辑

根据 OP 的建议,我将 panGestureRecognizer 添加到上述示例中。缩放本身完全由pinchGestureRecognizer 处理,但确实在大多数情况下,在将图像缩放到只有一部分可见的点之后,您需要平移以移动可见部分。也就是说,它是适当缩放体验的一部分。

【讨论】:

太棒了!我必须为panGestureRecognizer 做同样的事情,我很高兴!谢谢 :) (由于某种原因无法奖励赏金,我会稍后再做。) @matehat 我使用 swift 和我的 didEndDisplaying 单元格,我不断收到“发现 nil unwrapping optional”错误。我试过让它'如果让',它永远不会被调用。 :/这是我获取实例的方式:let cell = collectionView.cellForItemAtIndexPath(indexPath) as! FSImageCell 我不需要在单元格中添加/删除手势识别器。捏合和平移都已经在单元格中为我工作,同时仍然允许我水平滚动浏览我的收藏视图。我在图片库中使用全屏单元格。【参考方案3】:

请在您的单元格中添加滚动视图,并将您当前的单元格图像视图添加到滚动视图中。 然后使用下面的代码:

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

    ImageContext *context = [self.images objectAtIndex:indexPath.row];
    ImageCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"imageCell" forIndexPath:indexPath];
    cell.cellScrollView.autoresizesSubviews = YES;
    cell.cellScrollView.multipleTouchEnabled =YES;
    cell.cellScrollView.maximumZoomScale = 4.0;
    cell.cellScrollView.minimumZoomScale = 1.0;
    cell.cellScrollView.clipsToBounds = YES;
    cell.cellScrollView.delegate = self;
    cell.cellScrollView.zoomScale = 1.0;

    [cell.imageView setImage:[UIImage imageNamed:context.thumbImageUrl]];

return cell;

 -(UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
    NSLog(@"%i",scrollView.subviews.count);
  for (UIView *v in scrollView.subviews) 
    if ([v isKindOfClass:[UIImageView class]]) 
        return v;
      
  

【讨论】:

【参考方案4】:

检查所有相关视图的多点触控是否开启。 ios 在大多数视图上默认禁用多点触控以节省能源。

【讨论】:

我试过了,并试图模仿一些我能找到的例子,但我仍然无法让它工作。我在原始帖子中添加了一个 github repo url【参考方案5】:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
            
  if (touch.view == [self myScrollView]) //<- whatever your scrollView is called 
    
      return YES;
    
  return NO;

不知道您的代码,但请尝试使用上面的代码,看看您是否可以过滤您对所需对象的触摸。以上代码来自UIGestureRecognizerDelegate Protocol Reference。

【讨论】:

谢谢,我在collectionviewcell中添加了,里面好像没有为scrollview调用,只为outer view调用。【参考方案6】:

代理没有被调用,因为您在 UICollectionview 中添加了它。触摸事件可用于作为超级视图的集合视图,因此无法通过内部视图获得。您可能需要考虑其他一些方法来实现这个模型。

UICollectionViewUITableView 具有相同的模式,问题出现在滚动视图内的表格视图中,滚动视图[这是超级视图] 接受触摸事件并制作表格视图在这种情况下可滚动,必须禁用滚动视图的滚动。这是该问题的另一个版本

苹果文档说上述情况会产生不可预测的结果。所以这可能与您的问题相同。

在我看来,您必须寻求更好的设计,以实现您的目标

【讨论】:

【参考方案7】:
I've set the delegate of the UIScrollView to be the UICollectionViewCell, but none of the delegate methods are being called.

为此,只需在 collectionViewCell 中定义一个函数

  @IBOutlet weak var mainScrollView:UIScrollView!
  func setup()
        mainScrollView.minimumZoomScale=1
        mainScrollView.maximumZoomScale=10.0

        mainScrollView.delegate=self

    

   func viewForZooming(in scrollView: UIScrollView) -> UIView? 
        return yourimageviewinside of scrollview
    

调用这个函数 collectionview(_,cellForItem )collectionview的方法

【讨论】:

以上是关于如何在 UICollectionViewCell 内缩放 UIScrollView?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 iOS 7 中刷新 UICollectionViewCell?

如何在 UICollectionViewCell 内缩放 UIScrollView?

如何在重新加载时清除 UICollectionViewCell?

Swift:如何在 UICollectionViewCell 中使用“prepareForSegue”?

点击时如何在 UICollectionViewCell 中制作此动画?

如何确定何时显示 UICollectionViewCell?