问题描述
我的目标:使用几何读取器和屏幕截图功能(已编写)仅捕获落在关闭按钮后面的一小部分图像。
设置:我有一个带Image
的ZStack,它的上方有一个较小的按钮(此示例为系统映像)。目前,我的关闭按钮与背景图片的顶部对齐,乍一看一切都很好。
但是,当点击“关闭”按钮时,我需要截取“关闭”按钮本身的屏幕截图(与帧和大小匹配)。
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))
}
}
}