1

I would like to include the Navigation bar in my tableview screenshot image. The following code works to capture the entire tableview and I have tried other code that captures the Navigation bar but not the entire tableview. Is it possible to do both at the same time?

func screenshot(){
    var image = UIImage();

    UIGraphicsBeginImageContextWithOptions(CGSize(width:tableView.contentSize.width, height:tableView.contentSize.height),false, 0.0)
    let context = UIGraphicsGetCurrentContext()
    let previousFrame = tableView.frame
    tableView.frame = CGRect(x: tableView.frame.origin.x, y: tableView.frame.origin.y, width: tableView.contentSize.width, height: tableView.contentSize.height)
    tableView.layer.render(in: context!)
    tableView.frame = previousFrame
    image = UIGraphicsGetImageFromCurrentImageContext()!
    UIGraphicsEndImageContext()
    UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)

}

2 Answers2

1

Take navigation bar and tableview screenshots separately, then merge them.

Objective C:

-(UIImage*)merge:(UIImage*)tvImage with:(UIImage*)navImage {

    CGFloat contextHeight = tableView.contentSize.height + self.navigationController.navigationBar.frame.size.height;
    CGRect contextFrame = CGRectMake(0, 0, tableView.frame.size.width, contextHeight);

    UIGraphicsBeginImageContextWithOptions(contextFrame.size, NO, 0.0);
    CGContextRef context = UIGraphicsGetCurrentContext();
    UIGraphicsPushContext(context);


    //1 draw navigation image in context
    [navImage drawInRect:self.navigationController.navigationBar.frame];

    //2 draw tableview image in context
    CGFloat y = self.navigationController.navigationBar.frame.size.height;
    CGFloat h = tableView.contentSize.height;
    CGFloat w = tableView.frame.size.width;
    [tvImage drawInRect:CGRectMake(0, y, w, h)];


    // Clean up and get the new image.
    UIGraphicsPopContext();
    UIImage *mergeImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return mergeImage;

}

Swift 3:

func merge(tvImage:UIImage, with navImage:UIImage) {

        let contextHeight:CGFloat = tableView.contentSize.height + self.navigationController!.navigationBar.frame.size.height;
        let contextFrame:CGRect = CGRect(0, 0, tableView.frame.size.width, contextHeight);

        UIGraphicsBeginImageContextWithOptions(contextFrame.size, false, 0.0);
        let context:CGContext = UIGraphicsGetCurrentContext();
        UIGraphicsPushContext(context);


        //1 draw navigation image in context
        navImage.draw(in: self.navigationController.navigationBar.frame)


        //2 draw tableview image in context
        let y:CGFloat = self.navigationController.navigationBar.frame.size.height;
        let h:CGFloat = tableView.contentSize.height;
        let w:CGFloat = tableView.frame.size.width;
        tvImage.draw(in: CGRectMake(0, y, w, h))



        // Clean up and get the new image.
        UIGraphicsPopContext();
        let mergeImage:UIImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();

        return mergeImage;

    }
Baig
  • 4,737
  • 1
  • 32
  • 47
  • Thanks but I was looking for swift 3.0 code. I am a new developer and don't know Obj-C code. – Scott Townsend Aug 23 '17 at 14:30
  • @ScottTownsend i have added swift version, may it help. – Baig Aug 24 '17 at 06:45
  • I had to alter your code a little to get it to run. I made a CGRectMake helper method and changed No to false, but it does combine two images. I just don't know how to get a screenshot of only the navigation bar to combine the tableview with. – Scott Townsend Aug 25 '17 at 03:40
  • @ScottTownsend for taking screen shots use [this code snippet](https://stackoverflow.com/a/2203293/1556386) – Baig Aug 27 '17 at 05:44
0

Writing an extension will always help us to reuse. I have created a simple UIView extension check below

extension UIView  {
// render the view within the view's bounds, then capture it as image
   func asImage() -> UIImage {
     let renderer = UIGraphicsImageRenderer(bounds: bounds)
     return renderer.image(actions: { rendererContext in
         layer.render(in: rendererContext.cgContext)
     })
   }
}

Usage:

self.imageview.image = self.view.asImage() // If you want to capture the View
self.imageview.image = self.tabBarController?.view.asImage() // If it's TabbarViewController
Ramesh Boosa
  • 198
  • 8