0

ビュー/レイヤー階層は次のようになります。

CustomUIView  [A]
  |
  +--- UIImageView [B]

UI が最初に表示されると、ビュー [B] にデフォルトの画像 (ゲーム ボード) が表示されます。

ユーザー イベントに反応して、いくつかCALayerのオブジェクトを作成し、ビュー[A]のバッキング レイヤーにサブレイヤーとして追加します。次に、それらを使用してアニメーションをレンダリングし、ゲーム ボードのパーツを光学的に変更します。これは、階層的に画像ビューの上にあるためです。これはうまくいきます。

アニメーションが完了したら、結果のレイヤー状態のスクリーンショットを撮り、それを新しい画像として設定し[B]、ゲームの次の動きの前に一時的なサブレイヤーを破棄します。

私のコードは次のようになります。

[CATransaction begin];
[CATransaction setCompletionBlock:^{
    UIImage *snapshot = [self.view snapshot];
    self.snapshotVIew.image = snapshot;
    for (CALayer *tileLayer in tempLayers)
    {
        [tileLayer removeFromSuperlayer];
    }
}];

CAAnimationGroup *animGroup = [CAAnimationGroup animation];
animGroup.animations =@[contentAnimation, zoom];
animGroup.duration = 0.5f;
animGroup.removedOnCompletion = NO;
animGroup.fillMode = kCAFillModeForwards;
for (CALayer* tileLayer in tempLayers)
{
    [tileLayer addAnimation:animGroup forKey:nil];
}
[CATransaction commit];

私のカスタム ビューのスナップショット メソッドはかなり標準的です。

- (UIImage*) snapshot {
    UIGraphicsBeginImageContextWithOptions(self.bounds.size, YES, [[UIScreen mainScreen] scale]);
    [self.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage* img = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return img;
}

問題は、renderInContextのドキュメントに次のように記載されているようです。

レシーバーとそのサブレイヤーを指定されたコンテキストにレンダリングします。このメソッドは、レンダー ツリーに追加されたアニメーションを無視して、レイヤー ツリーから直接レンダリングします。

最後の強調表示された文のために、レイヤーが削除されると、すべてが以前と同じように見えます。どうやら、完了ブロックが実行されると、レイヤー ツリーが完成したアニメーション状態で更新されていないように見えるため、私のスクリーンショットではそれが考慮されていません。

どうすればこれを行うことができますか?

4

1 に答える 1

2

レイヤーのpresentationLayerをレンダリングしてみてください:

[self.layer.presentationLayer renderInContext:UIGraphicsGetCurrentContext()];

または、removedOnCompletion = NO を使用する代わりに、アニメーションを追加した後にレイヤーのプロパティを最終状態に設定します。アニメーションが完了すると、レイヤーは変更された外観を反映し、通常のレイヤーをレンダリングできます。

于 2012-06-25T18:23:17.767 に答える