【问题标题】:Covert UIVIew to UIImage without presenting/displaying UIView将 UIVIew 转换为 UIImage 而不呈现/显示 UIView
【发布时间】:2016-12-10 00:11:38
【问题描述】:

我正在使用方法将 UIView 转换为 UIImage,并且当 UIView(要转换为 UIImage)已经存在/显示时它做得很好。但我的要求是将 UIView 转换为 UIImage 而不显示 UIView。不幸的是,在这种情况下,这段代码失败了,我被卡住了。任何帮助将不胜感激。

我正在使用以下方法:

+ (UIImage *) imageWithView:(UIView *)view
{
    UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque,     [[UIScreen mainScreen] scale]); 
    [view.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return img;
}

【问题讨论】:

  • 只需隐藏 UIView 并获得图像的转换。
  • 隐藏视图对我不起作用,我也试过了。

标签: ios objective-c uiview xamarin.ios uiimage


【解决方案1】:

隐藏所有子视图,然后将 UIview 快照到 UIImage 应该可以工作,请参见下面的代码


+ (UIImage *)custom_snapshotScreenInView:(UIView *)contentView
{
    if (!contentView) {
        return nil;
    }
    CGSize size = contentView.bounds.size; 
    UIGraphicsBeginImageContextWithOptions(size, NO, [UIScreen mainScreen].scale); 
    CGRect rect = contentView.bounds; 
    [contentView drawViewHierarchyInRect:rect afterScreenUpdates:YES];
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 
    UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil); 
    return image;
}

+ (UIImage *)custom_snapshotScreenWithoutSubviews:(UIView *)contentView
{
    // save hidden view's hash
    NSMutableArray *hideViewsHashs = [[NSMutableArray alloc]initWithCapacity:contentView.subviews.count];
    for (UIView *subview in contentView.subviews) {
        if (subview.hidden == NO) {
            [hideViewsHashs addObject:@(subview.hash)];
            NSLog(@"Dikey:video:snap:hash = %@", @(subview.hash));
        }
        subview.hidden = YES;
    }
    // view to image
    UIImage *image = [UIImage custom_snapshotScreenInView:contentView];
    // restore
    for (UIView *subview in contentView.subviews) {
        if ([hideViewsHashs containsObject:@(subview.hash)]) {
            subview.hidden = NO;
            NSLog(@"Dikey:video:snap:restore:hash = %@", @(subview.hash));
        }
    }
    // finish
    return image;
}

【讨论】:

    【解决方案2】:

    假设您已经有了一个工作视图,这段代码应该可以将UIView 转换为UIImage(我正在使用它将渐变转换为图像并将图像显示到UIProgressView

    斯威夫特:

    let renderer = UIGraphicsImageRenderer(size: gradientView.bounds.size)
    let image = renderer.image { ctx in
                gradientView.drawHierarchy(in: gradientView.bounds, afterScreenUpdates: true)
    }
    

    目标 C:

    UIGraphicsImageRenderer *renderer = [[UIGraphicsImageRenderer alloc] initWithSize:gradientView.bounds.size];
    UIImage *gradientImage = [renderer imageWithActions:^(UIGraphicsImageRendererContext * _Nonnull rendererContext) {
            [gradientView drawViewHierarchyInRect:gradientView.bounds afterScreenUpdates:true];
        }];
    
    _progressView.progressImage = gradientImage;
    

    上面的代码应该允许您将任何UIView 转换为UIImage。理想情况下,您应该在 viewWillAppear 中运行它(因为此时视图控制器将具有正确的布局大小)。如果您在让它工作时遇到任何问题,您可以查看我为该主题的指南制作的这些示例项目! Objective C, Swift.

    【讨论】:

      【解决方案3】:

      您的代码可能会失败,因为您没有布置视图的子视图(当您将视图添加为子视图时会自动完成)。试试我下面写的方法:

      + (UIImage *)imageFromView:(UIView *)view sized:(CGSize)size
      {
          // layout the view
          view.frame = CGRectMake(0, 0, size.width, size.height);
          [view setNeedsLayout];
          [view layoutIfNeeded];
      
          // render the image
          UIGraphicsBeginImageContextWithOptions(size, view.opaque, 0.0f);
          [view drawViewHierarchyInRect:view.bounds afterScreenUpdates:NO];
          UIImage *renderedImage = UIGraphicsGetImageFromCurrentImageContext();
          UIGraphicsEndImageContext();
      
          return renderedImage;
      }
      

      【讨论】:

      • 说它“不工作”是没有帮助的。发生了什么事?
      • 使用上述代码未将视图转换为图像。这仅在屏幕上显示视图时有效。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-01-09
      • 2011-07-25
      • 2012-12-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多