【问题标题】:zoom entire UICollectionView缩放整个 UICollectionView
【发布时间】:2013-04-30 15:38:23
【问题描述】:

我有一个 iPad 应用程序,我在其中使用 UICollectionView,每个 UICollectionViewCell 只包含一个 UIImage。 目前我每页显示每 9 个 UIImages(3 行 * 3 列),我有几页。

我想使用 Pinch Gesture 缩放整个 UICollectionView 以增加/减少每页显示的行/列数,最好是在 Pinch 手势期间有漂亮的缩放动画!

目前,我在 UICollectionView 上添加了捏合手势。我捕获 Pinch Gesture 事件以使用比例因子计算行数/列数,如果它已更改,则我使用以下方法更新完整的 UICollectionView:

[_theCollectionView performBatchUpdates:^{
     [_theCollectionView deleteSections:[NSIndexSet indexSetWithIndex:0]];
     [_theCollectionView insertSections:[NSIndexSet indexSetWithIndex:0]];
 } completion:nil];

它可以工作,但我在过渡期间没有流畅的动画。

有什么想法吗? UICollectionView 继承自 UIScrollView,是否有可能重新使用 UIScrollView 捏手势功能来达到我的目标?

【问题讨论】:

    标签: ios uiscrollview zooming uicollectionview


    【解决方案1】:

    对不起,我的 2 美分问题,我找到了解决方案,非常简单。

    在我的PinchGesture 回调中,我刚刚完成了以下操作:

    void (^animateChangeWidth)() = ^() {
        _theFlowLayout.itemSize = cellSize;
    };
    
    [UIView transitionWithView:self.theCollectionView 
                      duration:0.1f 
                       options:UIViewAnimationOptionCurveLinear 
                    animations:animateChangeWidth 
                    completion:nil];
    

    我的UICollectionView 的所有单元格都已成功更改并带有漂亮的transition

    【讨论】:

    • 这不是处理缩放的正确方法,当布局失效[collectionView.collectionViewLayout invalidateLayout] 已经支持该功能时,您基本上是在强制重绘整个collectionView。我留下了一个更详尽的解释和示例的答案。
    • 拜托,你能补充更多细节吗?
    【解决方案2】:

    我假设您使用的是默认的 UICollectionViewDelegateFlowLayout,对吧?然后确保您对委托方法做出相应响应,并且当捏合手势发生时,只需使布局无效。

    例如,如果我想调整每个项目的大小,同时捏:

    @interface ViewController () <UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout>
    
    @property (nonatomic,assign) CGFloat scale;
    @property (nonatomic,weak)   IBOutlet UICollectionView *collectionView;
    
    @end
    
    @implementation ViewController
    - (void)viewDidLoad
    {
        [super viewDidLoad];
    
        self.scale = 1.0;
    
        [self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"cell"];
    
        UIPinchGestureRecognizer *gesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(didReceivePinchGesture:)];
        [self.collectionView addGestureRecognizer:gesture];
    
    }
    
    - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
    {
        return CGSizeMake(50*self.scale, 50*self.scale);
    }
    
    - (void)didReceivePinchGesture:(UIPinchGestureRecognizer*)gesture
    {
        static CGFloat scaleStart;
    
        if (gesture.state == UIGestureRecognizerStateBegan)
        {
            scaleStart = self.scale;
        }
        else if (gesture.state == UIGestureRecognizerStateChanged)
        {
            self.scale = scaleStart * gesture.scale;
            [self.collectionView.collectionViewLayout invalidateLayout];
        }
    }
    

    self.scale 属性只是为了展示,您可以将相同的概念应用于任何其他属性,这不需要 beginUpdates/endUpdates,因为用户自己携带刻度的时间。

    Here's a running project,如果你想看到它的实际效果。

    【讨论】:

    • +1 谢谢!检查了你的演示,它真的很有用。你能指导我们如何用漂亮的动画来展示这些过渡吗……我是 UICollectionView 的新手。
    • 很好的答案,如果您对布局更加“固定”并且您想要放大/缩小和平移(而不是移动项目)有任何见解,请问您是否有任何见解。例如,考虑一个地图,地图上的项目是 UICollectionCells,而图块可能是可重用的视图或类似的。
    • @MobileVet 在我的论文中,我编写了一个自定义 UICollectionViewLayout,它可以创建类似地图的东西,这完全有可能。如果您通过比例因子使集合视图布局报告的内容大小更大,那么您可以同时进行缩放和平移。
    • 这种无意中使内容比它需要的大得多,对吧? ://
    • @fatuhoku 好吧,是的。你有什么顾虑?
    【解决方案3】:

    对于 Xamarin.iOS 开发人员,我找到了这个解决方案:将 UIScrollView 元素添加到主视图,并将 UICollectionView 添加为 UIScrollView 的元素。然后为 UIScrollView 创建一个缩放代理。

    MainScrollView = new UIScrollView(new CGRect(View.Frame.X, View.Frame.Y, size.Width, size.Height));
    
            
            _cellReuseId = GenCellReuseId();
    
            _contentScroll = new UICollectionView(new CGRect(View.Frame.X, View.Frame.Y, size.Width, size.Height), new InfiniteScrollCollectionLayout(size.Width, size.Height));
            
            _contentScroll.AllowsSelection = true;
            _contentScroll.ReloadData();
    
    
            _contentScroll.Center = MainScrollView.Center;
            _contentScroll.Frame = new CGRect(_contentScroll.Frame.X, _contentScroll.Frame.Y - 32, _contentScroll.Frame.Width, _contentScroll.Frame.Height);
            MainScrollView.ContentSize = _contentScroll.ContentSize;
            MainScrollView.AddSubview(_contentScroll);
            MainScrollView.MaximumZoomScale = 4f;
            MainScrollView.MinimumZoomScale = 1f;
            MainScrollView.BouncesZoom = true;
            MainScrollView.ViewForZoomingInScrollView += (UIScrollView sv) =>
            {
                if (_contentScroll.Frame.Height < sv.Frame.Height && _contentScroll.Frame.Width < sv.Frame.Width)
                {
                    _contentScroll.Center = MainScrollView.Center;
                    _contentScroll.Frame = new CGRect(_contentScroll.Frame.X, _contentScroll.Frame.Y - 64, _contentScroll.Frame.Width, _contentScroll.Frame.Height);
                    _contentScroll.BouncesZoom = true;
                    _contentScroll.AlwaysBounceHorizontal = false;
                }
                return _contentScroll;
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-28
      • 2014-09-04
      • 1970-01-01
      • 1970-01-01
      • 2023-01-02
      相关资源
      最近更新 更多