开发者

Screenshot from a UITableView

开发者 https://www.devze.com 2023-03-14 03:19 出处:网络
I know there are many questions about this theme but I really read all of them but not found an answer.

I know there are many questions about this theme but I really read all of them but not found an answer.

I want make a screenshot from the current table view. and i do it this way:

-(UIImage *)imageFromCurrentView
{
    UIGraphicsBeginImageContextWithOptions(self.tableView.bounds.size, YES, 1);
    [self.tableView.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return img;
}

Everything works fine, but when i scroll down in the tableview and make the screenshot, half of the image is black. I don开发者_如何学Go't know how to make the screenshot from the actual tableview area.


This will get you the current visible region of the TableView.

If you want to render the entire tableview, first you need to be aware thats probably not a great idea for anything more than a few dozen rows because of memory and what not. The max image size in 2048x2048 so your tableView can be no taller than that.

UIView *viewToRender = self.tableView;
CGPoint contentOffset = self.tableView.contentOffset;

UIGraphicsBeginImageContext(viewToRender.bounds.size);

CGContextRef ctx = UIGraphicsGetCurrentContext();

//  KEY: need to translate the context down to the current visible portion of the tablview
CGContextTranslateCTM(ctx, 0, -contentOffset.y);

[viewToRender.layer renderInContext:ctx];

UIImage *image = UIGraphicsGetImageFromCurrentImageContext();

UIGraphicsEndImageContext();


take a look at this library I made to do exactly this, it has very useful methods like:

  1. Take a full screenshot of your UITableView (all the cells are rendered on a single UIImage)
  2. Take a screenshot for just a single cell given its indexPath
  3. Take a screenshot of just the headers, footers or rows of your UITableView

And more...

You can add it to your project via Cocoapods or manually by dragging the Source files.

The usage is so simple:

UIImage * tableViewScreenshot = [self.tableView screenshot];

I hope you find this library helpful as much as I do.


The following code works perfect in my application , you can use this code to capture screenshot of tableview or any other scrollview that has horizontal scrolling


CGPoint offset = [_tableView contentOffset];
_tableView.contentOffset = CGPointMake(0.0, 0.0);

CGRect visibleRect = _tableView.bounds;

UIGraphicsBeginImageContextWithOptions(_tableView.contentSize, _tableView.opaque, 0.0);

[_tableView.layer renderInContext:UIGraphicsGetCurrentContext()];

while (_tipsTableView.contentSize.height>= (visibleRect.origin.y+visibleRect.size.height)) {

    visibleRect.origin.y += visibleRect.size.height;

    [_tableView scrollRectToVisible:visibleRect animated:NO];
    [_tableView.layer renderInContext:UIGraphicsGetCurrentContext()];
}

UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();   

_tableView.contentOffset = offset;


Because UITableViewCell is reusable, when scrolling the table view, the cells outside the view ports will be enqueued for reusing and removed from the table view. So try to keep the cells only be reusable on its index path:

- (UITableViewCell *)tableView:(UITableView *)tableView
         cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
  NSString *cellIdentifier = [NSString stringWithFormat:@"Cell_%d_%d", indexPath.section, indexPath.row]; 
  UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
  if (cell == nil) {
    cell = [[[UITableViewCell alloc] initWithReuseIdentifier:cellIdentifier] autorelease];
  }
  ...
  return cell;
}

Not tested yet, give it a try. Yes, this will consume much more memory, do it with screenshot purpose only.

Edit: if you care the memory usage, may be you can take screenshot of current view port, then programmatically scroll top and down to take other parts of screenshots, and combine all the screen shots at last.


- (UIImage *) imageWithView:(UIView *)cellTobeCaptured isImage:(BOOL)isImage
{

//If UITableViewCell contains UIImageView

    if(isImage){
     UIGraphicsBeginImageContextWithOptions(cellTobeCaptured.bounds.size, NO, [UIScreen mainScreen].scale);
     [cellTobeCaptured drawViewHierarchyInRect:CGRectMake(0, 0, cellTobeCaptured.bounds.size.width, cellTobeCaptured.bounds.size.height) afterScreenUpdates:NO];
     UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
     UIGraphicsEndImageContext();
     return image;
    }
else{
  UIGraphicsBeginImageContextWithOptions(cellTobeCaptured.bounds.size, cellTobeCaptured.opaque, 0.0);
  [cellTobeCaptured.layer renderInContext:UIGraphicsGetCurrentContext()];
   UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
   UIGraphicsEndImageContext();
   return img;
   }
}

=> Call the method as

 UITableViewCell *cell = [tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:arrIndex inSection:0]];
 self->screenShotImage = [self imageWithView:cell isImage:YES];


I had a similar problem trying to replicate the Apple calendar scrolling when changing months in my own custom calendar built using a UITableView. After calling scrollToRowAtIndexPath:, making sure that animated: is YES so that scrollViewDidEndScrollingAnimation: is called, in scrollViewDidEndScrollingAnimation: I called reloadData: on the tableView before the renderInContext:. The full tableview was then rendered to the image. I ended up not using this in the long run so not sure of the reliability of it as a permanent solution but it worked well when I tried it.


For Swift 5 you can use this code

    let viewToRender = tableView;
    let contentOffset = tableView.contentOffset

    UIGraphicsBeginImageContext(viewToRender.bounds.size)

    if let ctx = UIGraphicsGetCurrentContext() {
       ctx.translateBy(x: 0, y: -contentOffset.y)

       viewToRender.layer.render(in: ctx)

       let image = UIGraphicsGetImageFromCurrentImageContext();

    }
    UIGraphicsEndImageContext();
0

精彩评论

暂无评论...
验证码 换一张
取 消