How to convert a View (not UIView) to an image?

前端 未结 4 587
醉梦人生
醉梦人生 2020-12-08 22:34

Similar to this thread

I would like to convert a SwiftUI View rather than a UIView to an image.

4条回答
  •  心在旅途
    2020-12-08 23:12

    Following kontiki answer, here is the Preferences way

    import SwiftUI
    
    struct ContentView: View {
        @State private var uiImage: UIImage? = nil
        @State private var rect1: CGRect = .zero
        @State private var rect2: CGRect = .zero
    
        var body: some View {
            VStack {
                HStack {
                    VStack {
                        Text("LEFT")
                        Text("VIEW")
                    }
                    .padding(20)
                    .background(Color.green)
                    .border(Color.blue, width: 5)
                    .getRect($rect1)
                    .onTapGesture {
                        self.uiImage =  self.rect1.uiImage
                    }
    
                    VStack {
                        Text("RIGHT")
                        Text("VIEW")
                    }
                    .padding(40)
                    .background(Color.yellow)
                    .border(Color.green, width: 5)
                    .getRect($rect2)
                    .onTapGesture {
                        self.uiImage =  self.rect2.uiImage
                    }
                }
    
                if uiImage != nil {
                    VStack {
                        Text("Captured Image")
                        Image(uiImage: self.uiImage!).padding(20).border(Color.black)
                    }.padding(20)
                }
            }
        }
    }
    
    struct ContentView_Previews: PreviewProvider {
        static var previews: some View {
            ContentView()
        }
    }
    
    extension CGRect {
        var uiImage: UIImage? {
            UIApplication.shared.windows
                .filter{ $0.isKeyWindow }
                .first?.rootViewController?.view
                .asImage(rect: self)
        }
    }
    
    extension View {
        func getRect(_ rect: Binding) -> some View {
            self.modifier(GetRect(rect: rect))
        }
    }
    
    struct GetRect: ViewModifier {
    
        @Binding var rect: CGRect
    
        var measureRect: some View {
            GeometryReader { proxy in
                Rectangle().fill(Color.clear)
                    .preference(key: RectPreferenceKey.self, value:  proxy.frame(in: .global))
            }
        }
    
        func body(content: Content) -> some View {
            content
                .background(measureRect)
                .onPreferenceChange(RectPreferenceKey.self) { (rect) in
                    if let rect = rect {
                        self.rect = rect
                    }
                }
    
        }
    }
    
    extension GetRect {
        struct RectPreferenceKey: PreferenceKey {
            static func reduce(value: inout CGRect?, nextValue: () -> CGRect?) {
                value = nextValue()
            }
    
            typealias Value = CGRect?
    
            static var defaultValue: CGRect? = nil
        }
    }
    
    extension UIView {
        func asImage(rect: CGRect) -> UIImage {
            let renderer = UIGraphicsImageRenderer(bounds: rect)
            return renderer.image { rendererContext in
                layer.render(in: rendererContext.cgContext)
            }
        }
    }
    
    

提交回复
热议问题