Using Swift 2.0 I am hoping to find a way to capture the resized image after the user has selected how they want to see it in the frame from the scroll view (ZoomScrollView).
I know there are complex examples out there from Swift but was hoping to find a simpler way to capture this in Swift 2.0. In all my searching I've heard references to using ZStack and some masks or overlays but can't find a simple good example.
I am hoping someone can update my example with the ZStack, masks, etc and how to extract the image for saving or provide a better example.
import SwiftUI
struct ContentView: View {
@Environment(\.presentationMode) var presentationMode
@State var isAccepted: Bool = false
@State var isShowingImagePicker = false
@State var isShowingActionPicker = false
@State var sourceType:UIImagePickerController.SourceType = .camera
@State var image:UIImage?
var body: some View {
HStack {
Color(UIColor.systemYellow).frame(width: 8)
VStack(alignment: .leading) {
HStack {
Spacer()
VStack {
if image != nil {
ZoomScrollView {
Image(uiImage: image!)
.resizable()
.scaledToFit()
}
.frame(width: 300, height: 300, alignment: .center)
.clipShape(Circle())
} else {
Image(systemName: "person.crop.circle")
.resizable()
.font(.system(size: 32, weight: .light))
.frame(width: 300, height: 300, alignment: .center)
.cornerRadius(180)
.foregroundColor(Color(.systemGray))
.clipShape(Circle())
}
}
Spacer()
}
Spacer()
HStack {
Button(action: {
self.isShowingActionPicker = true
}, label: {
Text("Select Image")
.foregroundColor(.blue)
})
.frame(width: 130)
.actionSheet(isPresented: $isShowingActionPicker, content: {
ActionSheet(title: Text("Select a profile avatar picture"), message: nil, buttons: [
.default(Text("Camera"), action: {
self.isShowingImagePicker = true
self.sourceType = .camera
}),
.default(Text("Photo Library"), action: {
self.isShowingImagePicker = true
self.sourceType = .photoLibrary
}),
.cancel()
])
})
.sheet(isPresented: $isShowingImagePicker) {
imagePicker(image: $image, isShowingImagePicker: $isShowingImagePicker ,sourceType: self.sourceType)
}
Spacer()
// Save button
Button(action: {
// Save Image here... print for now just see if file dimensions are the right size
print("saved: ", image!)
self.presentationMode.wrappedValue.dismiss()
}
) {
HStack {
Text("Save").foregroundColor(isAccepted ? .gray : .blue)
}
}
.frame(width: 102)
.padding(.top)
.padding(.bottom)
//.buttonStyle(RoundedCorners())
.disabled(isAccepted) // Disable if if already isAccepted is true
}
}
Spacer()
Color(UIColor.systemYellow).frame(width: 8)
}
.padding(.top, UIApplication.shared.windows.first?.safeAreaInsets.top)
.background(Color(UIColor.systemYellow))
}
}
struct ZoomScrollView<Content: View>: UIViewRepresentable {
private var content: Content
init(@ViewBuilder content: () -> Content) {
self.content = content()
}
func makeUIView(context: Context) -> UIScrollView {
// set up the UIScrollView
let scrollView = UIScrollView()
scrollView.delegate = context.coordinator // for viewForZooming(in:)
scrollView.maximumZoomScale = 20
scrollView.minimumZoomScale = 1
scrollView.bouncesZoom = true
// create a UIHostingController to hold our SwiftUI content
let hostedView = context.coordinator.hostingController.view!
hostedView.translatesAutoresizingMaskIntoConstraints = true
hostedView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
hostedView.frame = scrollView.bounds
scrollView.addSubview(hostedView)
return scrollView
}
func makeCoordinator() -> Coordinator {
return Coordinator(hostingController: UIHostingController(rootView: self.content))
}
func updateUIView(_ uiView: UIScrollView, context: Context) {
// update the hosting controller's SwiftUI content
context.coordinator.hostingController.rootView = self.content
assert(context.coordinator.hostingController.view.superview == uiView)
}
// MARK: - Coordinator
class Coordinator: NSObject, UIScrollViewDelegate {
var hostingController: UIHostingController<Content>
init(hostingController: UIHostingController<Content>) {
self.hostingController = hostingController
}
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return hostingController.view
}
}
}
struct imagePicker:UIViewControllerRepresentable {
@Binding var image: UIImage?
@Binding var isShowingImagePicker: Bool
typealias UIViewControllerType = UIImagePickerController
typealias Coordinator = imagePickerCoordinator
var sourceType:UIImagePickerController.SourceType = .camera
func makeUIViewController(context: Context) -> UIImagePickerController {
let picker = UIImagePickerController()
picker.sourceType = sourceType
picker.delegate = context.coordinator
return picker
}
func makeCoordinator() -> imagePickerCoordinator {
return imagePickerCoordinator(image: $image, isShowingImagePicker: $isShowingImagePicker)
}
func updateUIViewController(_ uiViewController: UIImagePickerController, context: Context) {}
}
class imagePickerCoordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
@Binding var image: UIImage?
@Binding var isShowingImagePicker: Bool
init(image:Binding<UIImage?>, isShowingImagePicker: Binding<Bool>) {
_image = image
_isShowingImagePicker = isShowingImagePicker
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let uiimage = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
image = uiimage
isShowingImagePicker = false
}
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
isShowingImagePicker = false
}
}
Just want to return the image that's zoomed in the circle. The image can be square (re: the 300x300 frame), that's fine just need the zoomed image not whole screen or the original image.