Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Isn't there an easy way to pinch to zoom in an image in Swiftui?

I want to be able to resize and move an image in SwiftUI (like if it were a map) with pinch to zoom and drag it around.

With UIKit I embedded the image into a UIScrollView and it took care of it, but I don't know how to do it in SwiftUI. I tried using MagnificationGesture but I cannot get it to work smoothly.

I've been searching about this for a while, does anyone know if there's an easier way?

like image 602
Zheoni Avatar asked Oct 11 '19 13:10

Zheoni


People also ask

How do you pinch and zoom?

If you're a Premium member, you can find the new feature in the YouTube app on Android; just tap your profile photo and then hit Your Premium benefits. From there, you can find the Try new features page and turn on YouTube's pinch to zoom. It may take a while to kick in until you can give this new tool a shot.

Does the pinch and zoom feature alter an image?

It does not create any color values that were not in the original image. This algorithm exaggerates the hard edges in the original image, but is an excellent method for highlighting exactly what the recording device captured.


1 Answers

The other answers here are overly complicated with custom zooming logic. If you want the standard, battle-tested UIScrollView zooming behavior you can just use a UIScrollView!

SwiftUI allows you to put any UIView inside an otherwise SwiftUI view hierarchy using UIViewRepresentable or UIViewControllerRepresentable. Then to put more SwiftUI content inside that view, you can use UIHostingController. Read more about SwiftUI–UIKit interop in Interfacing with UIKit and the API docs.

You can find a more complete example where I'm using this in a real app at: https://github.com/jtbandes/SpacePOD/blob/main/SpacePOD/ZoomableScrollView.swift (That example also includes more tricks for centering the image.)

var body: some View {   ZoomableScrollView {     Image("Your image here")   } }  
struct ZoomableScrollView<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     }   } } 
like image 127
jtbandes Avatar answered Sep 19 '22 11:09

jtbandes