先上代码
- (void)btnAction:(UIButton *)sender {
// self.tableView.frame = CGRectMake(0, 0, WIDTHOFSCREEN, 10000);
UIImage* image = nil;
// 下面方法,第一个参数表示区域大小。第二个参数表示是否是非透明的。如果需要显示半透明效果,需要传NO,否则传YES。第三个参数就是屏幕密度了,调整清晰度。
UIGraphicsBeginImageContextWithOptions(self.tableView.contentSize, YES, [UIScreen mainScreen].scale);
CGPoint savedContentOffset = self.tableView.contentOffset;
CGRect savedFrame = self.tableView.frame;
self.tableView.contentOffset = CGPointZero;
self.tableView.frame = CGRectMake(0, 0, self.tableView.contentSize.width, self.tableView.contentSize.height);
[self.tableView.layer renderInContext: UIGraphicsGetCurrentContext()];
image = UIGraphicsGetImageFromCurrentImageContext();
self.tableView.contentOffset = savedContentOffset;
self.tableView.frame = savedFrame;
UIGraphicsEndImageContext();
if (image != nil) {
//保存图片到相册
UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), NULL);
}
}
//指定回调方法
- (void)image: (UIImage *) image didFinishSavingWithError: (NSError *) error contextInfo: (void *) contextInfo {
NSString *msg = nil ;
if(error != NULL)
{
msg = @"保存图片失败"
;
}else{
msg = @"保存图片成功,可到相册查看" ;
}
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"信息提示" message:msg delegate:self cancelButtonTitle:@"确定" otherButtonTitles:nil];
[alert show];
}
代码的思路是:
- 先指定contentSize大小的画板上下文
- 将tableview的frame大小设为contentSize大小 目的是cell全加载
- 保存原frame contentoffset 截屏后还原
截屏效果图:
针对上面代码列几个可能面临的问题
- cell是复用,未展示时cell上是没有数据的 未展示的cell怎么截?cell的复用是以展示在屏幕上进行复用,还是进入tableview上进行复用?需要一次性加载所有cell
下面的代码可以确认cell是以是否超出tableview来进行复用
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
_tableView = [[UITableView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 2500) style:UITableViewStylePlain];
[self.view addSubview:_tableView];
_tableView.backgroundColor = [UIColor lightGrayColor];
_tableView.delegate = self;
_tableView.dataSource = self;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 50;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"aa"];
if (!cell) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"aa"];
}
cell.contentView.backgroundColor = [UIColor greenColor];
// cell.contentView.alpha = 1.0/(indexPath.row + 1);
cell.textLabel.text = [NSString stringWithFormat:@"%ld",indexPath.row];
NSLog(@"默认展示到=====%ld",indexPath.row);
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 50;
}
- autolayout时cell高度是预估高度,所以contentsize也是预估的,可能比真实的大也可能比真实的小,所以以预估的contentsize来截图有问题。那么我们就需要获取真实的contentsize
解决方案:autolayout下可使用UITableView+FDTemplateLayoutCell来解决 - 如果cell上有图片,加载图片有个过程,截屏完成很快图片没加载出来怎么办?这个处理起来尤其麻烦 (1. 用户来回滚先把图片预加载2.把所有要渲染的图片用sddownloader预下载。。)
解决方案:笨方法遍历当前数据模型将网络图片全部加载一遍加载完成后再截屏 - 截出来的图片太大有没有优化空间
- 滑动一段距离后再截屏 会出现黑屏
//网上的代码思路
- (UIImage *)cutOutTableViewForImage:(UITableView *)scrollView{
UIImage*image = nil;
CGPoint savedContentOffset = scrollView.contentOffset;
CGRect savedFrame = scrollView.frame;
CGSize contentSize = scrollView.contentSize;
CGRect oldBounds = scrollView.layer.bounds;
if(@available(iOS 13.0, *)){
[scrollView.layer setBounds:CGRectMake(oldBounds.origin.x, oldBounds.origin.y,contentSize.width, contentSize.height)];
}
UIGraphicsBeginImageContextWithOptions(scrollView.contentSize, NO, [UIScreen mainScreen].scale);
scrollView.contentOffset = CGPointZero;
scrollView.frame=CGRectMake(0,0,contentSize.width, contentSize.height);
[scrollView.layer renderInContext:UIGraphicsGetCurrentContext()];
if(@available(iOS 13.0, *)){
[scrollView.layer setBounds:oldBounds];
}
image = UIGraphicsGetImageFromCurrentImageContext();
scrollView.contentOffset= savedContentOffset;
scrollView.frame= savedFrame;
UIGraphicsEndImageContext();
return image;
}
//和上面思路一样
UIScrollView *listView = (UIScrollView *)theView;
UIView *childVCView = listView.superview;
CGFloat originHeight = childVCView.height;
childVCView.height = listView.contentSize.height;
UIImage *contentViewImage = [XLUtil screenLongShotWithView:childVCView];
childVCView.height = originHeight;
+ (UIImage *)screenLongShotWithView:(UIView *)view withAnimatingView:(BOOL)saveAnimate {
UIImage* image = nil;
UIGraphicsBeginImageContextWithOptions(view.bounds.size, YES, 0.0);
//在当前上下文中渲染出collectionView
CALayer *layer;
if (saveAnimate) {
layer = [view.layer presentationLayer];
}else {
layer = view.layer;
}
[layer renderInContext: UIGraphicsGetCurrentContext()];
//截取当前上下文生成Image
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
if (image != nil) {
return image;
}else {
return nil;
}
}
网友评论