29

スクロール ビューのアニメーション ズームに従ってコンテンツ ビューの要素 (複数のCALayersを管理するサブビュー) を更新できるように、スクロール ビューのスケールを注意深く監視する必要があります。

iOS 3.1 では、すべてが期待どおりに動作します。zoomToRect:animated:を使用し、 UIScrollViewDelegatescrollViewDidScroll:メッセージがアニメーションの実行中に繰り返し呼び出されるため、実際のズームに応じてサブビュー要素を更新できます。

iOS 4.0 の同じコードは、同じ動作を示しません。zoomToRect:animated:を呼び出すと、デリゲート ( scrollViewDidScroll:およびscrollViewDidZoom ) は一度しか呼び出されないため、アニメーションが終了するまでサブ要素の同期が解除されます。実際、サブ要素はすぐにジャンプし、すべてが正しい場所に配置されるまで、ズーム アニメーションに追いつきます。アニメーションがサブビューCALayersの変更を反映していないようです。

アニメーション ブロックを使用して手動でアニメーション化を試みましたが、状況は同じで、プログレッシブ コールバック呼び出しはありません。KVO も試してみましたが、UIScrollView で管理されたアニメーションをどのように利用するかは明確ではありません。

UIScrollViewスケールがアニメーション化されているときに、スケール値をサブビューにプッシュできる iOS 4 の回避策はありますか?

4

4 に答える 4

10

残忍ですが動作します。

いくつかのプロパティを定義します。

@property (nonatomic, strong) UIView *zoomedView;    
@property (nonatomic, strong) CADisplayLink *displayLink;
@property (nonatomic) CGFloat currentScale;

UIScrollViewズームするUIView予定の通知:

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
     return self.zoomedView;
}

CADisplayLinkダニに登録します。Core Animationも実行されるため、同じ間隔でキックされます。

self.displayLink  = [CADisplayLink displayLinkWithTarget:self selector:@selector(displayLinkTick)];
[self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];

presentationLayer現在の値については、zoomedViewを確認してください。

- (void)displayLinkTick
{
    CALayer *zoomedLayer = self.zoomedView.layer.presentationLayer;
    CGFloat scale = zoomedLayer.transform.m11;

    if (scale != self.currentScale) {
         self.currentScale = scale; // update property

         // the scale has changed!
    }
}
于 2013-03-19T23:08:59.930 に答える
1

IOS 4.0 では、アニメーションは OS によって行われます。GPU ベースのハードウェア アクセラレーションを可能な限り利用することを想定しています。その欠点として、別の (アニメーション化された) 値から派生した値をアニメーション化することが難しくなります。あなたの場合のように、UIScrollView のズーム レベルに依存するサブビューの位置。これを実現するには、ズームのアニメーションと並行してサブビューのアニメーションを設定する必要があります。次のようなものを試してください:

[UIView animateWithDuration:0.5 delay:0
                    options:UIViewAnimationOptionLayoutSubviews
                 animations:^{
    theScrollView.zoomScale = zoomScale;
    // layout the subviews here
} completion:^(BOOL finished) {}];

これにより、同じアニメーション コンテキスト内からサブビューのフレーム プロパティが設定されるため、OS によって一緒にアニメーション化される必要があります。

この質問への回答も参照してください:アニメーション中に UIScrollView が scrollViewDidScroll メッセージを送信するようにする方法

于 2011-09-26T10:50:59.903 に答える
-1

アニメーションブロック(またはbegin / commitAnimation)内のすべてのサブビューを更新することは実行可能ですか?何かのようなもの:

[self zoomToRect:zoomRect animated:YES];
[UIView animateWithDuration:1.0
    animations:^ {
        // change your subviews
    }
];
于 2010-11-12T15:06:58.820 に答える
-1

に電話した後、 のzoomScaleプロパティのKVO に登録します。UIScrollViewzoomToRect:animated:

[scrollView addObserver:self
            forKeyPath:@"zoomScale"
               options:(NSKeyValueObservingOptionNew |
                        NSKeyValueObservingOptionOld)
                context:NULL];

次に、このメソッドを実装します。

- (void)observeValueForKeyPath:(NSString *)keyPath
              ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context
{
    if ([keyPath isEqual:@"zoomScale"]) {
    // use the new zoomScale value stored
    // in the NSKeyValueChangeNewKey change
    // dictionary key  to resize your subviews
    }
    // be sure to call the super implementation
    // if the superclass implements it
    [super observeValueForKeyPath:keyPath
                ofObject:object
                 change:change
                 context:context];
}

KVO のドキュメントを参照してください。

于 2010-11-15T20:15:29.447 に答える