この記事について
UITableViewのキャプチャを簡単に撮る方法の紹介です。
というのも、MySplitTimeというアプリを作成する際、出来上がったスプリットをシェアするのに、画像化してシェアしようと考えたところ、いくつか方法を見つけたものの、スクロールする方法やダミーViewを作って画像化する方法。
もっとシンプルに出来るのでは、と思ったところ安定のStackOverflowにあったので、その紹介を。
https://stackoverflow.com/questions/37049770/capture-uitableview-as-image-with-scrolling
UITableViewだけのキャプチャを撮る方法
/**
TableViewだけのキャプチャを作成
*/
func createViewImage() -> UIImage? {
// キャプチャサイズにTableViewのcontentSizeを指定
let captureSize = tableView.contentSize
print("captureSize = \(captureSize)")
// context生成
UIGraphicsBeginImageContextWithOptions(captureSize, false, 0.0)
// tableViewのframe退避
let previousFrame = tableView.frame
if let context = UIGraphicsGetCurrentContext(){
// tableviewのframeを、コンテンツサイズに一時的に変更
tableView.frame = CGRect(x:tableView.frame.origin.x,
y:tableView.frame.origin.y,
width:tableView.contentSize.width,
height:tableView.contentSize.height)
// tableViewのレイヤを描画
tableView.layer.render(in: context)
}
// tableViewのframe復帰
tableView.frame = previousFrame
// image生成
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext();
return image
}
ポイントは2つ
・キャプチャを撮るためにcontextのサイズは、tableViewのcontentSizeとする
・キャプチャ取得のときだけ、layer.renderの前にtableView.frameをコンテンツサイズに変更
全体キャプチャを撮る方法
viewcontroller.viewのキャプチャだけでは可視範囲だけになってしまいます。
全体を撮るために、contextのサイズをtableViewのcontentSize + その他の領域とする必要があります。
/**
TableViewとImageViewのキャプチャを生成する
・TableViewより上の部分は、self.viewからのキャプチャとする
・そのキャプチャに被せるようにtableViewのキャプチャを載せる
*/
func createViewImage() -> UIImage? {
// キャプチャサイズ計算
let captureSize = CGSize(width: self.view.frame.size.width,
height: self.imageHolderView.frame.size.height + tableView.contentSize.height)
print("captureSize = \(captureSize)")
// context生成
UIGraphicsBeginImageContextWithOptions(captureSize, false, 0.0)
// tableViewのframe退避
let previousFrame = tableView.frame
// UINavigationController調整
var topAdjust: CGFloat = 0
if let _ = self.navigationController {
// 最上部に描画するViewからy座標の位置分調整する
// もしくは、NavigationControllerの高さとステータスバーの高さを調整としても良い
topAdjust = self.imageHolderView.frame.origin.y
}
if let context = UIGraphicsGetCurrentContext(){
// NavigationControllerが描画域に入らないように調整して描画
context.translateBy(x: 0, y: -topAdjust)
self.view.layer.render(in: context)
context.translateBy(x: 0, y: topAdjust)
// tableViewの描画にむけ、contextをimageView分だけ移動
context.translateBy(x: 0, y: self.imageHolderView.frame.size.height)
// tableviewのframeを、コンテンツサイズに一時的に変更
tableView.frame = CGRect(x:tableView.frame.origin.x,
y:tableView.frame.origin.y,
width:tableView.contentSize.width,
height:tableView.contentSize.height)
// tableViewのレイヤを描画
tableView.layer.render(in: context)
}
// tableViewのframe復帰
tableView.frame = previousFrame
// image生成
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext();
return image
}
上記はviewcontroller.viewとtableViewのキャプチャを繋げるようにしています。
viewcontroller.viewのframeを、描画域外のcontentSize.height分足して上げるほうがよりシンプルかもしれません。
(UINavigationControllerがある場合は、self.view.layer.renderにその分の上部余白が生まれることを考慮する必要があります)
サンプル
githubにサンプルコードを載せてます
https://github.com/dchssk/TableViewCapture
これを実際に使って公開しているアプリです
https://itunes.apple.com/jp/app/mysplittime/id1437885505?mt=8