0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

UITableViewのキャプチャを簡単に撮る方法

Last updated at Posted at 2019-01-22

この記事について

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

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?