Delay contextMenu on SwiftUI

484 views Asked by At

I'm trying to delay when the contextMenu appears because I have a drag gesture which causes me this view when trying to drag with some kind of accidental delay.

…
Text(exampleText)
  .contextMenu
  {
    delay()

    // Menus here
  }
  .gesture(
    DragGesture()
      .onEnded(
        { end in
          switch exampleTextAlignment
          {
            case .leading:
              if end.translation.width > 0
              {
                exampleTextAlignment = .center
              }
            case .center:
            if end.translation.width < 0
              {
                exampleTextAlignment = .leading
              }
            else if end.translation.width > 0
              {
                exampleTextAlignment = .trailing
              }
            case .trailing:
              if end.translation.width < 0
              {
                exampleTextAlignment = .center
              }
          }
        }
      )
    )
…

…where delay() is:

…
private func delay() async {
        try? await Task.sleep(nanoseconds: UInt64(secondsHere * Double(NSEC_PER_SEC)))
        hasTimeElapsed = true
    }
…

Expected result.

Xcode v.13.2 and iOS v.15.2.

1

There are 1 answers

0
ChrisR On

this works perfectly for me:

struct ContentView: View {
    
    let exampleText = "I'm trying to delay when the contextMenu appears because I have a drag gesture which causes me this view when trying to drag with some kind of accidental delay."
    
    @State private var exampleTextAlignment: TextAlignment = .center
    
    var body: some View {
        VStack {
            Text(exampleText)
                .multilineTextAlignment(exampleTextAlignment)
                .contextMenu {
                    // Menus here
                    Button("Test") {}
                }
                .gesture(DragGesture()
                            .onEnded { end in
                    switch exampleTextAlignment
                    {
                    case .leading:
                        if end.translation.width > 0 {
                            exampleTextAlignment = .center
                            //  onContextMenuAlignment = .top
                        }
                    case .center:
                        if end.translation.width < 0 {
                            exampleTextAlignment = .leading
                            //  onContextMenuAlignment = .topLeading
                        }
                        else if end.translation.width > 0 {
                            exampleTextAlignment = .trailing
                            //   onContextMenuAlignment = .topTrailing
                        }
                    case .trailing:
                        if end.translation.width < 0 {
                            exampleTextAlignment = .center
                            //   onContextMenuAlignment = .top
                        }
                    default: break
                    }
                }
            )
        }
        .padding()
    }
}