swiftui - GeometryReader 和 ZStack 到产品截图
问题描述
我的目标:使用几何阅读器和屏幕截图功能(已经编写)来抓取位于关闭按钮后面的图像的一小部分。
设置:我有一个 ZStack,上面有Image
一个较小的按钮(它是本示例的系统映像)。目前,我将关闭按钮与背景图像的顶部对齐,乍一看一切都很好。
但是,当点击关闭按钮时,我需要抓取关闭按钮本身的屏幕截图(匹配框架和大小)。
当我对齐时一切正常,但现在我已经设置ZStack
,我的屏幕截图仍然出现在图像的中心。.center
alignment: .top
当点击它时,如何移动GeometryReader
包含关闭按钮的屏幕截图以允许屏幕截图成为关闭按钮(以及它背后的一些额外背景)?
我的代码:
struct ImageView: View {
var body: some View {
ZStack(alignment: .top) {
Image("ZoomedBuzz")
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: UIScreen.main.bounds.width)
GeometryReader { geo in
Image(systemName: "xmark.circle.fill")
.font(.system(size: 80))
.border(Color.blue)
.onTapGesture {
let globalImage = takeScreenshot(origin: geo.frame(in: .global).origin,
size: geo.size)
print(globalImage)
}
}
.frame(width: 80, height: 80, alignment: .top)
}
}
}
截图:
extension UIView {
var renderedImage: UIImage {
// rect of capture
let rect = self.bounds
// create the context of bitmap
UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0)
let context: CGContext = UIGraphicsGetCurrentContext()!
self.layer.render(in: context)
// get a image from current context bitmap
let capturedImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return capturedImage
}
}
extension View {
func takeScreenshot(origin: CGPoint, size: CGSize) -> UIImage {
let window = UIWindow(frame: CGRect(origin: origin, size: size))
let hosting = UIHostingController(rootView: self)
hosting.view.frame = window.frame
window.addSubview(hosting.view)
window.makeKeyAndVisible()
return hosting.view.renderedImage
}
}
期望的结果(但在顶部ZStack
):
当前结果(在以 为中心的背景图像中间截取屏幕截图ZStack
):
解决方案
如果您希望 GeometryReader 靠近按钮而不是捕获整个屏幕,您可以将其设置为按钮背景。
不幸的是,我不知道你的截图方法是如何工作的,因此我无法验证它是否适用于你的设置,但现在你可以简单地截图整个 GeometryReader 的框架。
struct ImageView: View {
@State private var geo: GeometryProxy!
var body: some View {
ZStack(alignment: .top) {
Image("ZoomedBuzz")
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: UIScreen.main.bounds.width)
Image(systemName: "xmark.circle.fill")
.font(.system(size: 80))
.border(Color.blue)
.background(rectReader())
.onTapGesture {
let globalImage = takeScreenshot(origin: geo.frame(in: .global).origin,
size: geo.size)
print(globalImage)
}
}
}
private func rectReader() -> some View {
return GeometryReader { geometry -> AnyView in
DispatchQueue.main.async {
self.geo = geometry
}
return AnyView(Rectangle().fill(Color.clear))
}
}
}
推荐阅读
- laravel - 在 laravel cron 中迭代服务提供者
- python-3.x - 无法“激活”烧瓶的 venv 环境
- android - 我可以使用具有相同包名的 2 个不同的 firebase 项目吗?
- r - 通过 R 进行网页抓取
- android - 安装 Delphi 10.4 Android SDK 的问题
- javascript - 如何在自定义古腾堡块中使用图库上传器
- jenkins - 将 vagrant 上的 ssh-agent 转发给 vagrant 以外的其他用户
- snowflake-cloud-data-platform - 如何基于使用多个角色和多个数据库的查询在 Snowflake 中创建视图?
- asp.net-mvc - routeconfig 中的 async/await 方法面临问题
- git - 无法在 Git 中更改文件的状态