LoginSignup
0
0

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