【问题标题】:What is the best way to rotate a view in swift and convert it to an image?快速旋转视图并将其转换为图像的最佳方法是什么?
【发布时间】:2020-02-21 18:20:37
【问题描述】:

我的任务是在 Swift 中创建动态“票证”。我从我们的服务器 API 传递了票号、金额等,我将生成条形码以及与此票关联的所有标签。我能够毫无问题地生成所有必要的数据。

问题

问题在于布局。我需要这张票的缩略图视图以及全屏视图。这似乎最好通过将视图转换为图像来完成(对吗?),因为它允许缩放、缩略图视图等功能。问题的主要原因是 需要放置票标签和条形码垂直或基本上以横向模式。

我尝试过的

UIGraphicsBeginImageContext

我已经使用UIGraphicsBeginImageContext() 和相关的 API 手动创建了图像。这使我可以翻转每个视图并将其转换为图像。然而,这种方法迫使我为每个视图手动创建一个框架并且失去了所有准确性,并且当我必须向空白图像添加 10-15 个标签时,这似乎不是正确的方法。

自动布局

接下来,我尝试使用自动布局在 UIView 中布置所有内容,并将CGAffineTransform 应用于每个视图,然后将整个视图转换为图像。除了我失去精度并且无法正确排列视图之外,这似乎有效。 CGAffineTransform 完全摆脱了约束,我必须尝试使用​​约束常量,直到我的视图看起来有点正确,即使这样也不能很好地转换到所有设备尺寸。

横向模式

最后,我尝试正常布局视图,并强制视图进入横向模式。除了因为我的应用程序仅支持纵向模式而出现的许多问题之外,我在呈现视图时让它工作,但我不知道如何获取应该在工单视图呈现之前显示的缩略图视图处于横向模式。如果我尝试这样做,缩略图会以纵向模式而不是横向模式出现。

你们对完成此任务的更好方法有任何想法,还是我应该坚持我尝试过的一种方法并尝试解决所有错误?我可以根据需要提供代码,但其中有很多内容,所以如果没有必要,我不想把所有代码都扔在这里。

以下是我需要创建的示例,但我需要在其中添加其他标签,例如发行日期、到期日期等:

任何帮助将不胜感激!

【问题讨论】:

  • 我会查看嵌套的UIStackViews。
  • 另外,请将您的帖子限制在一个问题上。您的标题与您在文本中描述的不同。另请参阅How to Ask,如果可能,请提供您已经尝试过的minimal reproducible example
  • 转换为图像似乎不是您的最佳策略。您可以像这样旋转stackoverflow.com/a/56355145/5329717 并使用自定义框架、变换等调整视图的大小/重新缩放视图。通过转换为光栅图像,您很可能最终会破坏字体。你有很多方法可以在 UIKit 中以编程方式完成。

标签: ios swift autolayout


【解决方案1】:

你问:

快速旋转视图并将其转换为图像的最佳方法是什么?

如果您想创建视图的旋转快照,请将 rotatetranslateBy 应用于上下文:

func clockwiseSnapshot(of subview: UIView) -> UIImage {
    var rect = subview.bounds
    swap(&rect.size.width, &rect.size.height)
    return UIGraphicsImageRenderer(bounds: rect).image { context in
        context.cgContext.rotate(by: .pi / 2)
        context.cgContext.translateBy(x: 0, y: -rect.width)
        subview.drawHierarchy(in: subview.bounds, afterScreenUpdates: true)
    }
}

或者

func counterClockwiseSnapshot(of subview: UIView) -> UIImage {
    var rect = subview.bounds
    swap(&rect.size.width, &rect.size.height)
    return UIGraphicsImageRenderer(bounds: rect).image { context in
        context.cgContext.rotate(by: -.pi / 2)
        context.cgContext.translateBy(x: -rect.height, y: 0)
        subview.drawHierarchy(in: subview.bounds, afterScreenUpdates: true)
    }
}

显然,如果您希望Data 与图像关联,请改用pngDatajpegData

func clockwiseSnapshotData(of subview: UIView) -> Data {
    var rect = subview.bounds
    swap(&rect.size.width, &rect.size.height)
    return UIGraphicsImageRenderer(bounds: rect).pngData { context in
        context.cgContext.rotate(by: .pi / 2)
        context.cgContext.translateBy(x: 0, y: -rect.width)
        subview.drawHierarchy(in: subview.bounds, afterScreenUpdates: true)
    }
}

或者

func counterClockwiseSnapshotData(of subview: UIView) -> Data {
    var rect = subview.bounds
    swap(&rect.size.width, &rect.size.height)
    return UIGraphicsImageRenderer(bounds: rect).pngData { context in
        context.cgContext.rotate(by: -.pi / 2)
        context.cgContext.translateBy(x: -rect.height, y: 0)
        subview.drawHierarchy(in: subview.bounds, afterScreenUpdates: true)
    }
}

如果您并不真正需要该图像,而只是想在 UI 中旋转它,则将 transform 应用于包含所有这些子视图的视图:

someView.transform = .init(rotationAngle: .pi / 2)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-21
    • 2017-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-27
    相关资源
    最近更新 更多