skip to Main Content

Hello I have a Drag Gesture function. You can see what this function is for by looking at the code.

My problem is this: I just want the view to move down to a certain extent. How can I do that?

func onChanged(value: DragGesture.Value){
    
    if value.startLocation.y < value.location.y  {
        
        playerModel.offset = value.translation
        
        let screenHeight = UIScreen.main.bounds.width - 50
        let progress = playerModel.offset.height / screenHeight
        
        
        if 1 - progress > 0.925 {
            playerModel.scale = 1 - progress
        }
    }
}

2

Answers


  1. Here’s an example of how to limit movement of a draggable rectangle that recognizes device rotation and doesn’t use GeometryReader.

    import SwiftUI
    
    struct ContentView: View {
      @State private var currentPosition: CGSize = .zero
      @State private var newPosition: CGSize = .zero
      @State private var screenBounds: CGRect = .zero
      @State private var boundsPosition: CGSize = .zero
      @State private var orientation = UIDevice.current.orientation
      let widthLimit: CGFloat = 100
      let heightLimit: CGFloat = 100
      let orientationChanged = NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification)
        .makeConnectable()
        .autoconnect()
      
      var body: some View {
        Rectangle()
          .frame(width: 100, height: 100)
          .foregroundColor(.green)
          .offset(x: currentPosition.width, y: currentPosition.height)
          .onAppear() {
           currentPosition = .zero
           newPosition = .zero
            setTravelLimits()
            limitTravel()
          }
          .onReceive(orientationChanged) {_ in
            setTravelLimits()
            limitTravel()
          }
          .gesture(
            DragGesture()
              .onChanged { value in
                currentPosition = CGSize(width: value.translation.width + newPosition.width, height: value.translation.height + newPosition.height)
                limitTravel()
              }
              .onEnded { value in
                currentPosition = CGSize(width: value.translation.width + newPosition.width, height: value.translation.height + newPosition.height)
                limitTravel()
                newPosition = currentPosition
              })
      }
      
      func setTravelLimits() {
        screenBounds = UIScreen.main.bounds
        boundsPosition.width = (screenBounds.width / 2) - widthLimit
        boundsPosition.height = (screenBounds.height / 2) - heightLimit
      }
      
      func limitTravel() {
        currentPosition.height = currentPosition.height > boundsPosition.height ? boundsPosition.height: currentPosition.height
       currentPosition.height = currentPosition.height < -boundsPosition.height ? -boundsPosition.height: currentPosition.height
        currentPosition.width = currentPosition.width > boundsPosition.width ? boundsPosition.width: currentPosition.width
        currentPosition.width = currentPosition.width < -boundsPosition.width ? -boundsPosition.width: currentPosition.width
      }
    }
    
    Login or Signup to reply.
  2. Try this:

    struct ContentView: View {
      @State private var currentPosition: CGSize = .zero
      @State private var newPosition: CGSize = .zero
      @State private var screenBounds: CGRect = .zero
      @State private var boundsPosition: CGSize = .zero
      @State private var verticalLimit: CGSize = .zero
      @State private var orientation = UIDevice.current.orientation
      let heightLimit: CGFloat = 100
      let orientationChanged = NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification)
        .makeConnectable()
        .autoconnect()
      
      var body: some View {
        Rectangle()
          .frame(width: 100, height: 100)
          .foregroundColor(.green)
          .offset(x: currentPosition.width, y: currentPosition.height)
          .onAppear() {
            currentPosition = .zero
            newPosition = .zero
            setTravelLimits()
            limitTravel()
          }
          .onReceive(orientationChanged) {_ in
            setTravelLimits()
            limitTravel()
          }
          .gesture(
            DragGesture()
              .onChanged { value in
                verticalLimit.height = currentPosition.height
                currentPosition = CGSize(width: value.translation.width + newPosition.width, height: value.translation.height +  newPosition.height)
                limitTravel()
              }
              .onEnded { value in
                currentPosition = CGSize(width: value.translation.width + newPosition.width, height: value.translation.height + newPosition.height)
                limitTravel()
                newPosition = currentPosition
              })
      }
      
      func setTravelLimits() {
        screenBounds = UIScreen.main.bounds
        boundsPosition.width = 0
        boundsPosition.height = (screenBounds.height / 2 ) - heightLimit
      }
      
      func limitTravel() {
        currentPosition.height = currentPosition.height < boundsPosition.height ? currentPosition.height: boundsPosition.height
        currentPosition.height = currentPosition.height > verticalLimit.height ? currentPosition.height: verticalLimit.height
        currentPosition.width = currentPosition.width > boundsPosition.width ? boundsPosition.width: currentPosition.width
        currentPosition.width = currentPosition.width < -boundsPosition.width ? -boundsPosition.width: currentPosition.width
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search