How to render a whole UITableView as an UIImage in iOS?

后端 未结 13 2139
太阳男子
太阳男子 2020-12-17 23:54

I have simple UITableView with some data. The table\'s height is greater than the screen size. Now I need to catch screenshot of this table (a whole table). I k

相关标签:
13条回答
  • 2020-12-18 00:18

    I have same requirement to send image of tableview to admin via email, Hope this will help you. Function implemented in swift 4

    func screenshot() -> UIImage{
        var image = UIImage()
    
        UIGraphicsBeginImageContextWithOptions(self.tblDetails.contentSize, false, UIScreen.main.scale)
    
        // save initial values
        let savedContentOffset = self.tblDetails.contentOffset
        let savedFrame = self.tblDetails.frame
        let savedBackgroundColor = self.tblDetails.backgroundColor
    
        // reset offset to top left point
        self.tblDetails.contentOffset = CGPoint(x: 0, y: 0)
        // set frame to content size
        self.tblDetails.frame = CGRect(x: 0, y: 0, width: self.tblDetails.contentSize.width, height: self.tblDetails.contentSize.height)
        // remove background
        self.tblDetails.backgroundColor = UIColor.clear
    
        // make temp view with scroll view content size
        // a workaround for issue when image on ipad was drawn incorrectly
        let tempView = UIView(frame: CGRect(x: 0, y: 0, width: self.tblDetails.contentSize.width, height: self.tblDetails.contentSize.height))
    
        // save superview
        let tempSuperView = self.tblDetails.superview
        // remove scrollView from old superview
        self.tblDetails.removeFromSuperview()
        // and add to tempView
        tempView.addSubview(self.tblDetails)
    
        // render view
        // drawViewHierarchyInRect not working correctly
        tempView.layer.render(in: UIGraphicsGetCurrentContext()!)
        // and get image
        image = UIGraphicsGetImageFromCurrentImageContext()!
    
        // and return everything back
        tempView.subviews[0].removeFromSuperview()
        tempSuperView?.addSubview(self.tblDetails)
    
        // restore saved settings
        self.tblDetails.contentOffset = savedContentOffset
        self.tblDetails.frame = savedFrame
        self.tblDetails.backgroundColor = savedBackgroundColor
    
        UIGraphicsEndImageContext()
    
        return image
    }
    
    0 讨论(0)
  • 2020-12-18 00:19

    Just UITableView's cells to UIImage

    UIGraphicsBeginImageContextWithOptions(CGSizeMake(tableView.contentSize.width, tableView.contentSize.height+64+40), true, 0)
    
    for section in 0...tableView.numberOfSections-1 {
        for row in 0...tableView.numberOfRowsInSection(section)-1 {
            let indexPath = NSIndexPath.init(forRow: row, inSection: section)
            let cell = tableView.cellForRowAtIndexPath(indexPath)!
    
            print("row:\(indexPath.row), frame:\(cell.frame) height:\(cell.frame.height)")
    
            cell.contentView.drawViewHierarchyInRect(cell.frame, afterScreenUpdates: true)
        }
    }
    let image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    
    0 讨论(0)
  • 2020-12-18 00:20

    Try this:

     func generateImage(tblview:UITableView) ->UIImage{
            UIGraphicsBeginImageContext(tblview.contentSize);
            tblview.scrollToRowAtIndexPath(NSIndexPath(forRow: 0, inSection: 0), atScrollPosition: UITableViewScrollPosition.Top, animated: false)
            tblview.layer.renderInContext(UIGraphicsGetCurrentContext())
            let row = tblview.numberOfRowsInSection(0)
            let numberofRowthatShowinscreen = 4
            var scrollCount = row / numberofRowthatShowinscreen
    
            for var i=0;i < scrollCount ; i++ {
                tblview.scrollToRowAtIndexPath(NSIndexPath(forRow: (i+1)*numberofRowthatShowinscreen, inSection: 0), atScrollPosition: UITableViewScrollPosition.Top, animated: false)
                tblview.layer.renderInContext(UIGraphicsGetCurrentContext())
            }
    
            let image:UIImage = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext();
            return image;
    }
    

    and after call method like this.

     var imageView = UIImageView()
         imageView.image =generateImage(tableView)
    
    0 讨论(0)
  • 2020-12-18 00:23
    UIGraphicsBeginImageContextWithOptions(CGSizeMake(self.tableView.contentSize.width, self.tableView.contentSize.height), YES, 0);
    
    CGFloat originY = 0;
    
    CGRect rectFirst =  CGRectMake(0, originY, self.tableView.bounds.size.width, self.view.bounds.size.height);
    
    [self.tableView scrollRectToVisible:rectFirst animated:NO];
    
    [self.tableView drawViewHierarchyInRect:rectFirst afterScreenUpdates:true];
    
    while (originY < self.tableView.contentSize.height) {
    
       CGRect rectSecond =  CGRectMake(0, originY, self.tableView.bounds.size.width, self.view.bounds.size.height);
    
        [self.tableView scrollRectToVisible: rectSecond animated:NO];
    
        [self.tableView drawViewHierarchyInRect: rectSecond afterScreenUpdates:true];
    
        originY += self.view.bounds.size.height;
    
    }
    
    CGRect rectFinally =  CGRectMake(0, originY, self.tableView.bounds.size.width, self.tableView.contentSize.height - originY);
    
    [self.tableView scrollRectToVisible:rectFinally animated:NO];
    
    [self.tableView drawViewHierarchyInRect:rectFinally afterScreenUpdates:true];
    
    UIImage * image = UIGraphicsGetImageFromCurrentImageContext();  
    
    UIGraphicsEndImageContext();
    

    It's very important to set animated to NO, and don't block the UI thread

    0 讨论(0)
  • 2020-12-18 00:25

    To take a screenshot of an UIView you can use the following:

    UIGraphicsBeginImageContext(tableview.frame.size)
    tableview.layer.renderInContext(UIGraphicsGetCurrentContext())
    let image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext() 
    

    This will work for whatever is visible, and may work for any already loaded but off-screen views.
    In an UITableView, only the visible cells plus 1 off-screen cell at each end of the table are loaded. The other ones do not actually exist... yet. So you can't "capture" them.

    0 讨论(0)
  • 2020-12-18 00:26

    My solution for Swift 4 !

    import Foundation
    import UIKit
    
    extension UITableView {
    
        func asFullImage() -> UIImage? {
    
            guard self.numberOfSections > 0, self.numberOfRows(inSection: 0) > 0 else {
                return nil
            }
    
            self.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: false)
    
            var height: CGFloat = 0.0
            for section in 0..<self.numberOfSections {
                var cellHeight: CGFloat = 0.0
                for row in 0..<self.numberOfRows(inSection: section) {
                    let indexPath = IndexPath(row: row, section: section)
                    guard let cell = self.cellForRow(at: indexPath) else { continue }
                    cellHeight = cell.frame.size.height
                }
                height += cellHeight * CGFloat(self.numberOfRows(inSection: section))
            }
    
            UIGraphicsBeginImageContextWithOptions(CGSize(width: self.contentSize.width, height: height), false, UIScreen.main.scale)
    
            for section in 0..<self.numberOfSections {
                for row in 0..<self.numberOfRows(inSection: section) {
                    let indexPath = IndexPath(row: row, section: section)
                    guard let cell = self.cellForRow(at: indexPath) else { continue }
                    cell.contentView.drawHierarchy(in: cell.frame, afterScreenUpdates: true)
    
                    if row < self.numberOfRows(inSection: section) - 1 {
                        self.scrollToRow(at: IndexPath(row: row+1, section: section), at: .bottom, animated: false)
                    }
                }
            }
            let image = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
    
            return image!
        }
    }
    
    
    0 讨论(0)
提交回复
热议问题