我有一个简单的UITableView
,其中包含一些数据。表格的高度大于屏幕大小。现在我需要捕获这个表格的截图(整个表格)。我知道内容后面的单元格会被回收,但也许有一种方法可以捕获它们。不是吗?
我有一个简单的UITableView
,其中包含一些数据。表格的高度大于屏幕大小。现在我需要捕获这个表格的截图(整个表格)。我知道内容后面的单元格会被回收,但也许有一种方法可以捕获它们。不是吗?
试试这个:
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 numberofRowsThatShowOnScreen = 4
var scrollCount = row / numberofRowthatShowinscreen
for var i = 0; i < scrollCount; i++ {
tblview.scrollToRowAtIndexPath(NSIndexPath(forRow: (i+1) * numberofRowsThatShowOnScreen, inSection: 0), atScrollPosition: UITableViewScrollPosition.Top, animated: false)
tblview.layer.renderInContext(UIGraphicsGetCurrentContext())
}
let image:UIImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext();
return image;
}
var imageView = UIImageView()
imageView.image = generateImage(tableView)
我的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!
}
}
将UITableView的cell转换为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()
Young Hoo Kim的回答的Swift 3版本适用于我:
func generateTableViewImage(_ tableView: UITableView) -> UIImage? {
UIGraphicsBeginImageContextWithOptions(tableView.contentSize, false, UIScreen.main.scale)
for section in 0..<tableView.numberOfSections {
for row in 0..<tableView.numberOfRows(inSection: section) {
let indexPath = IndexPath(row: row, section: section)
guard let cell = tableView.cellForRow(at: indexPath) else { continue }
cell.contentView.drawHierarchy(in: cell.frame, afterScreenUpdates: true)
}
}
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image
}
Parth Bhadaja的回答的Swift 4版本:
func generateImage(tableView:UITableView) -> UIImage {
UIGraphicsBeginImageContext(tableView.contentSize);
tableView.scrollToRow(at: NSIndexPath(row: 0, section: 0) as IndexPath, at: UITableViewScrollPosition.top, animated: false)
tableView.layer.render(in: UIGraphicsGetCurrentContext()!)
let row = tableView.numberOfRows(inSection: 0)
let numberofRowthatShowinscreen = 4
let scrollCount = row / numberofRowthatShowinscreen
for i in 0..<scrollCount {
tableView.scrollToRow(at: NSIndexPath(row: (i+1)*numberofRowthatShowinscreen, section: 0) as IndexPath, at: UITableViewScrollPosition.top, animated: false)
tableView.layer.render(in: UIGraphicsGetCurrentContext()!)
}
let image:UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext();
return image;
}
要截取一个 UIView 的屏幕截图,可以使用以下代码:
UIGraphicsBeginImageContext(tableview.frame.size)
tableview.layer.renderInContext(UIGraphicsGetCurrentContext())
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
category
,向UITableView
添加render
方法。- (UIImage *)render {
//save the origin info for later to restore
CGPoint originContentOffset = self.contentOffset;
//force jump to table view's top
self.contentOffset = CGPointZero;
UIGraphicsBeginImageContext(self.contentSize);
CGContextRef *ctx = UIGraphicsGetCurrentContext();
//render header
[self.tableHeaderView.layer renderInContext:ctx];
//render sections
NSInteger numberOfSections = [self numberOfSections];
for (int section = 0; section < numberOfSections; section++) {
NSInteger numberOfRows = [self numberOfRowsInSection:section];
for (int row = 0; row < numberOfRows; row++) {
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:row inSection:section];
//check cell is visible
if ([self cellForRowAtIndexPath:indexPath]) {
[self scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:false];
[self.layer renderInContext:ctx];
}
}
}
//render footer
[self.tableFooterView.layer renderInContext:ctx];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
//restore info
self.contentOffset = originContentOffset;
return image;
}
将Parth Bhadaja的答案转换为Swift 3,并作为扩展使用计算属性:
extension UITableView {
var capturedImage : UIImage {
UIGraphicsBeginImageContext(contentSize);
scrollToRow(at: NSIndexPath(row: 0, section: 0) as IndexPath, at: UITableViewScrollPosition.top, animated: false)
layer.render(in: UIGraphicsGetCurrentContext()!)
let row = numberOfRows(inSection: 0)
let numberofRowthatShowinscreen = 4
let scrollCount = row / numberofRowthatShowinscreen
for i in 0 ..< scrollCount {
scrollToRow(at: NSIndexPath(row: (i+1)*numberofRowthatShowinscreen, section: 0) as IndexPath, at: UITableViewScrollPosition.top, animated: false)
layer.render(in: UIGraphicsGetCurrentContext()!)
}
let image:UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext();
return image;
}
}
使用方法:
let image = tableView.capturedImage
您可以使用tableView.contentSize的大小创建图形上下文。之后,您必须遍历所有indexPath并绘制每个单元格。您可以有一个单元格用于重复使用以绘制屏幕外的单元格 - 只需更改所需数据的内容并进行绘制即可。
这里提供一种替代方案,带有一些小的改进:
tableHeaderView
和 tableFooterView
)。如果从第一行开始捕获,有时无法完全获取内容。contentOffset
以便在滚动+捕获完成后再次设置它。extension UITableView {
var tableViewAsImage: UIImage? {
let offset = contentOffset
UIGraphicsBeginImageContext(contentSize)
guard let currentContext = UIGraphicsGetCurrentContext() else {
return nil
}
setContentOffset(.zero, animated: false)
layer.render(in: currentContext)
let height = bounds.height
let totalHeight = contentSize.height
let scrollCount = Int((height / totalHeight).rounded())
for i in 0...scrollCount {
let y: CGFloat = CGFloat(i) * height
setContentOffset(.init(x: 0, y: y), animated: false)
layer.render(in: currentContext)
}
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
setContentOffset(offset, animated: false)
return image
}
}