//余計なUIをキャプチャしないように隠す
hogeButton.isHidden = true
hogeLabel.isHidden = true
CATransaction.flush() //画面更新
//viewと同じサイズのコンテキスト(オフスクリーンバッファ)を作成
let rect = self.view.bounds
UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0)
//スクリーンをコンテキストに描画 = スクリーンキャプチャ
self.view.drawHierarchy(in: view.bounds, afterScreenUpdates: false)
//スクリーンがキャプチャされたコンテキストからUIImageを作成
let capturedImage : UIImage = UIGraphicsGetImageFromCurrentImageContext()!
//コンテキストの扱いを終了
UIGraphicsEndImageContext()
//隠したUIを表示させる
hogeButton.isHidden = false
hogeLabel.isHidden = false
アニメの途中が表示されない問題
詳しいことはわからんのだが、アニメのメソッドで指定してる最後の移動位置でキャプチャされちゃうみたい。
つまり、AからBの位置に5秒間で移動するアニメを実行中、3秒目でキャプチャしてもなぜかキャプチャ画像だけはBの位置に来てる。(画面上ではまだ途中を動いてるというのに)
renderやdrawじゃなくdrawHierarchy
それを回避するため、drawHierarchy()メソッドを使うのがいいようだ。ただし、afterScreenUpdatesがtrueの場合は同じような問題が発生するので、falseにしなければいけない。
直前のhiddenが効かない新たな問題
でもfalseにすると、写したくないUI部品をキャプチャ動作の直前でhiddenしても、hiddenされなくて写り込んでしまう。UI部品をhiddenした直後にsetNeedsDisplay()とかやってもダメ。これは画面更新の予約だけで、実際に更新されるのはOS次第なんだそうな。
よくわからんがflush()で解決
そこで調べたところ、部品をhiddenした直後に CATransaction.flush() をしたところうまくいった。一瞬部品がhiddenされ、スクリーンキャプチャされた後にまた部品が表示される。
CATransactionはCALayerのアニメを使うためのクラスだそうで、flush()はRunLoop終わりで自動的に呼ばれるものを強制的に(?)実行させるものらしい。
flashじゃなくてflushな。顔を赤らめるとか、興奮、感情の芽生え、トイレの貯水槽とかの意味がある。なんだよそれ!?w
正直言ってUIViewのメソッドじゃないのにうまくいくのは納得いかないんだけど、結果オーライでいいや。
0 件のコメント:
コメントを投稿