2018.9.19
本文提供了 UIView,UIScrollView,UITableView
三个常用的视图的代码截图方法,三者的思路都是一样的,即将所有显示内容渲染到一个上下文对象中去,然后将这个上下文对象保存成UIImage
对象就OK了。
UIView 截图
简单的设置上下文对象,然后调用几句代码就好了,关键在于设置
UIView
的大小,以及比例系数(影响清晰度?),方便起见建议写入UIImage
的分类中;
+ (UIImage *)CapturedWithUIView:(UIView *)view {
// 下面方法,第一个参数表示区域大小。第二个参数表示是否是非透明的。如果需要显示半透明效果,需要传NO,否则传YES。第三个参数就是屏幕密度了,关键就是第三个参数。
UIGraphicsBeginImageContextWithOptions(view.bounds.size, NO, [UIScreen mainScreen].scale);
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
UIScrollView 截图
其实方法和
UIView
的截图方法基本没有区别,如果将设置一个UIView
的父视图,大小为UIScrollView
的contentSize
的大小,那么用UIView
的截图方法应该也是没问题的;方便起见建议写入UIImage
的分类中;
+ (UIImage *)CapturedWithUIScrollView:(UIScrollView *)scrollView {
UIImage* image = nil;
UIGraphicsBeginImageContextWithOptions(scrollView.contentSize, NO, [UIScreen mainScreen].scale);
{
CGPoint savedContentOffset = scrollView.contentOffset;
CGRect savedFrame = scrollView.frame;
scrollView.contentOffset = CGPointZero;
scrollView.frame = CGRectMake(0, 0, scrollView.contentSize.width, scrollView.contentSize.height);
[scrollView.layer renderInContext:UIGraphicsGetCurrentContext()];
image = UIGraphicsGetImageFromCurrentImageContext();
scrollView.contentOffset = savedContentOffset;
scrollView.frame = savedFrame;
}
UIGraphicsEndImageContext();
return image;
}
UITableView 截图
这个地方有点麻烦的就是
Cell
可能是重用的,也就说上面的方法不能适用了,因为Cell
的内容都没有被绘制到上下文对象中,当然也就无法成功截图了。。。
处理思路同样是想办法将所有的视图渲染到上下文对象中去,然后将上下文对象转成UIImage实例;方便起见建议写入UIImage的分类中;
这个,我的最终实现方法还是比较糙的,若是哪位猿兄有更好的处理方式,还请不吝赐教了啊;
注:1.需要实现协议方法 - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section 或 - (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section 时,首先需要实现相应的返回高度的协议方法,其次一定要用UITableViewHeaderFooterView类创建实例,并返回这个实例,这样下面的方法中才可以用 headerViewForSection 或 footerViewForSection 取得相关视图实例;
2.如果像QQ好友列表那样的折叠情况,我觉得可以复制这个TableView,然后设定为不折叠,即只要保证所有视图的高度值能被方法成功获取到就可以了;
参考:UITableView screenshot
+ (UIImage *)CapturedWithUITableView:(UITableView *)tableView {
CGPoint savedContentOffset = tableView.contentOffset;
///计算画布所需实际高度
CGFloat contentHeight = 0;
if (tableView.tableHeaderView)
contentHeight += tableView.tableHeaderView.frame.size.height;
{
NSInteger sections = tableView.numberOfSections;
for (NSInteger i = 0; i < sections; i++) {
contentHeight += [tableView rectForHeaderInSection:i].size.height;
NSInteger rows = [tableView numberOfRowsInSection:i];
{
for (NSInteger j = 0; j < rows; j++) {
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:j inSection:i];
[tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionNone animated:NO];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
contentHeight += cell.frame.size.height;
}
}
contentHeight += [tableView rectForFooterInSection:i].size.height;
}
}
if (tableView.tableFooterView)
contentHeight += tableView.tableFooterView.frame.size.height;
///创建画布
UIGraphicsBeginImageContextWithOptions(CGSizeMake(tableView.frame.size.width, contentHeight), NO, [UIScreen mainScreen].scale);
CGContextRef ctx = UIGraphicsGetCurrentContext();
///把所有的视图 render到CGContext上
if (tableView.tableHeaderView) {
contentHeight = tableView.tableHeaderView.frame.size.height;
tableView.contentOffset = CGPointMake(0, contentHeight);
[tableView.tableHeaderView.layer renderInContext:ctx];
CGContextTranslateCTM(ctx, 0, tableView.tableHeaderView.frame.size.height);
}
NSInteger sections = tableView.numberOfSections;
for (NSInteger i = 0; i < sections; i++) {
///sectionHeader
contentHeight += [tableView rectForHeaderInSection:i].size.height;
tableView.contentOffset = CGPointMake(0, contentHeight);
UIView *headerView = [tableView headerViewForSection:i];
if (headerView) {
[headerView.layer renderInContext:ctx];
CGContextTranslateCTM(ctx, 0, headerView.frame.size.height);
}
///Cell
NSInteger rows = [tableView numberOfRowsInSection:i];
{
for (NSInteger j = 0; j < rows; j++) {
//讓該cell被正確的產生在tableView上, 之後才能在CGContext上正確的render出來
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:j inSection:i];
[tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionNone animated:NO];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
contentHeight += cell.frame.size.height;
[cell.layer renderInContext:ctx];
CGContextTranslateCTM(ctx, 0, cell.frame.size.height);
}
}
///sectionFooter
contentHeight += [tableView rectForFooterInSection:i].size.height;
tableView.contentOffset = CGPointMake(0, contentHeight);
UIView *footerView = [tableView footerViewForSection:i];
if (footerView) {
[footerView.layer renderInContext:ctx];
CGContextTranslateCTM(ctx, 0, footerView.frame.size.height);
}
}
if (tableView.tableFooterView) {
tableView.contentOffset = CGPointMake(0, tableView.contentSize.height-tableView.frame.size.height);
[tableView.tableFooterView.layer renderInContext:ctx];
//CGContextTranslateCTM(ctx, 0, tableView.tableFooterView.frame.size.height);
}
///生成UIImage对象
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
tableView.contentOffset = savedContentOffset;
return image;
}