【问题标题】:Can you convert uiview that is not currently being displayed to uiimage你能把当前没有显示的uiview转换成uiimage吗
【发布时间】:2019-07-08 12:24:41
【问题描述】:

我发现了许多将 UIView 转换为 UIImage 的示例,一旦视图布局等,它们就可以完美地工作。即使在我的视图控制器中有很多行,其中一些还没有显示在屏幕上,我也可以进行转换。不幸的是,对于一些在表格中太靠后的视图(因此还没有被“绘制”),进行转换会产生一个空白的 UIImage。

我尝试调用 setNeedsDisplay 和 layoutIfNeeded,但这些都不起作用。我什至尝试过自动滚动表格,但也许我没有以确保滚动首先发生的方式(使用线程)在转换发生之前允许视图更新。我怀疑这无法完成,因为我发现了各种各样的问题,但都没有找到解决方案。或者,我是否可以只在 UIImage 中重绘整个视图,而不需要 UIView?

来自 Paul Hudson 的网站

使用任何未在屏幕上显示的 UIView(比如 UITableview 中位于屏幕底部下方的一行。

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

【问题讨论】:

  • 你能澄清一下这样做的目的吗?
  • 你不能这样做,它只适用于当前呈现在(或关闭)屏幕上的视图。我想不出任何简单的方法来做到这一点。也许您可以以编程方式从上到下滚动表格,并在每个单元格出现时一个一个地创建 UIImage。感觉很hacky,但它可以工作。
  • 我的应用程序有表格视图,其中包含多行上的大量图表(例如 6 到 10 行)。我想把这些从应用程序中拿出来与他人分享。拍摄快照很好,但速度慢且麻烦。对于某些应用程序,我还想裁剪快照以仅包含屏幕截图的相关部分,即感兴趣的 uiview。因此,我创建了一个共享按钮,并希望一次将所有 6 或 10 个视图转储到共享中(发送到电子邮件、空投或添加到照片库),但它只会为那些不在屏幕上的视图提供空白。

标签: ios swift uiview uiimage


【解决方案1】:

您不必在窗口/屏幕上拥有视图即可将其渲染为图像。我已经在PixelTest 中做到了这一点:

extension UIView {

    /// Creates an image from the view's contents, using its layer.
    ///
    /// - Returns: An image, or nil if an image couldn't be created.
    func image() -> UIImage? {
        UIGraphicsBeginImageContextWithOptions(bounds.size, false, 0)
        guard let context = UIGraphicsGetCurrentContext() else { return nil }
        context.saveGState()
        layer.render(in: context)
        context.restoreGState()
        guard let image = UIGraphicsGetImageFromCurrentImageContext() else { return nil }
        UIGraphicsEndImageContext()
        return image
    }

}

如果要在屏幕上渲染,这会将视图的图层渲染为当前外观。也就是说,如果视图还没有被布局,那么它看起来就不会是你期望的样子。 PixelTest 通过在验证视图以进行快照测试时预先强制布局视图来做到这一点。

【讨论】:

  • 我不相信。有用!太感谢了。你知道这个网站上至少有五个这样的问题还没有解决,即没有提供解决方案。你真是个天才。
  • 此方法使用我的 xib 的默认高度和宽度来生成 UIImage。如何让它为我的快照使用自定义尺寸?
【解决方案2】:

您也可以使用UIGraphicsImageRenderer 完成此操作。

extension UIView {

    func image() -> UIImage {
        let imageRenderer = UIGraphicsImageRenderer(bounds: bounds)
        if let format = imageRenderer.format as? UIGraphicsImageRendererFormat {
            format.opaque = true
        }
        let image = imageRenderer.image { context in
            return layer.render(in: context.cgContext)
        }
        return image
    }

}

【讨论】:

  • 谢谢。这也可以,但现在背景是白色的,而在上面的方法中,我可以选择 opaque 为真(并得到黑色背景)。
  • 您可以使用UIGraphicsImageRendererformat (UIGraphicsImageRendererFormat) 属性来更改不透明值。
  • 谢谢。完美运行。如何将两个答案都标记为正确。
  • 此方法使用我的 xib 的默认高度和宽度来生成 UIImage。如何让它为我的快照使用自定义尺寸?
  • 可以更改方法签名并传递bounds参数:function image(customDimensions: CGRect = bounds)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-10
  • 2023-01-22
  • 1970-01-01
  • 2020-09-19
  • 1970-01-01
相关资源
最近更新 更多