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?
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.
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.
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 } } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With