9

UICollectionView を使用している iPad アプリがあり、各 UICollectionViewCell には UIImage が 1 つだけ含まれています。現在、ページごとに 9 つの UIImages (3 行 * 3 列) ごとに表示しています。複数のページがあります。

ピンチ ジェスチャーを使用して UICollectionView 全体をズームし、ページごとに表示される行/列の数を増減させたいと考えています。ピンチ ジェスチャー中に美しいズーム アニメーションを表示するのが最適です。

現在、UICollectionView にピンチ ジェスチャーを追加しました。Pinch Gesture イベントをキャッチして、スケール ファクターを使用して行/列の数を計算します。変更されている場合は、以下を使用して完全な UICollectionView を更新します。

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

動作しますが、移行中のアニメーションがスムーズではありません。

何か案が?UICollectionView は UIScrollView を継承していますが、UIScrollView のピンチ ジェスチャ機能を再利用して目標を達成することはできますか?

4

3 に答える 3

30

デフォルトの 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 は必要ありません。

実際の動作を見たい場合は、ここに実行中のプロジェクトがあります。

于 2013-07-08T02:01:14.397 に答える
1

2 セントの質問で申し訳ありませんが、非常に簡単な解決策を見つけました。

私のPinchGestureコールバックでは、次のことを行いました。

void (^animateChangeWidth)() = ^() {
    _theFlowLayout.itemSize = cellSize;
};

[UIView transitionWithView:self.theCollectionView 
                  duration:0.1f 
                   options:UIViewAnimationOptionCurveLinear 
                animations:animateChangeWidth 
                completion:nil];

私のすべてのセルUICollectionViewは正常に変更され、素敵なtransition.

于 2013-05-06T22:14:02.190 に答える
0

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;
};
于 2020-03-27T09:29:28.463 に答える