1

Using Swift5.3.2, iOS14.4.1, Xcode12.4,

I am trying to use the .simultaneousGesture modifier in SwiftUI.

As far as I understood, this modifier should make sure that gestures (such as tap, longpress, magnification etc) should be able to co-exist within a View.

In my example I am using a ZoomableScrollView. And it works fine as long as I do not use the simultaneousGesture.

But as soon as I use the extra simultaneousGesture, the ZoomableScrollView is no longer "zoomable" (i.e. none of its gestures work anymore).

What can I do to make the zoom still work AND get an extra dragGesture ?

import SwiftUI

struct MediaTabView: View {
    
    @GestureState private var dragOffset: CGFloat = -100
    
    var body: some View {

        ZoomableScrollView {
            Image(uiImage: UIImage(contentsOfFile: url.path)!)
                .resizable()
                .scaledToFit()
            }
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .background(Color.black)
        .simultaneousGesture(
            DragGesture()
                .updating($dragOffset) { (value, gestureState, transaction) in
                    let delta = value.location.x - value.startLocation.x
                    if delta > 10 { // << some appropriate horizontal threshold here
                        gestureState = delta
                        print(delta)
                    }
                }
                .onEnded {
                    if $0.translation.width > 100 {
                        // Go to the previous slide
                        print("on ended")
                    }
                }
        )        
    }
}

The code for the ZoomableScrollView is here :

import SwiftUI

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
    hostedView.backgroundColor = .black
    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
    }
  }
}
iKK
  • 6,394
  • 10
  • 58
  • 131

0 Answers0