简体   繁体   中英

SwiftUI TabView with simultaneousGesture

I have a TabView with some views that have DragGesture s inside. I want to be able to drag the views along with the TabView paging. I am trying to use simultaneousGesture for the drag gesture. This works with a ScrollView but not with a TabView . As you can see in the example the green square on the second page can be dragged around but this doesn't happen simultaneously with the TabView s horizontal scrolling.

Here is a simplified version of the code:

struct ContentView: View {
  let colors:[Color] = [.red, .green, .blue]
  @State private var location: CGPoint = CGPoint(x: 100, y: 100);

  var simpleDrag: some Gesture {
    DragGesture()
      .onChanged { value in
        self.location = value.location
      }
      .onEnded {_ in }
  }

  var body: some View {
    TabView{
      ForEach(colors, id: \.self) { color in
        Group {
          if color == .green {
            VStack {
              color
                .frame(width:100, height: 100)
                .position(location)
                .simultaneousGesture(simpleDrag)
            }
          } else {
            color
          }
        }
        .frame(width: 200, height: 200)
      }
    }
    .frame(width: 400, height: 400)
    .tabViewStyle(.page(indexDisplayMode: .never))
  }
}

And here is a version with a ScrollView that works really well, it even scrolls the scroll view when moving side to side and moves the green box when dragging it up and down.

struct ContentView: View {
  let colors:[Color] = [.red, .green, .blue]
  @State private var location: CGPoint = CGPoint(x: 100, y: 100);

  var simpleDrag: some Gesture {
    DragGesture()
      .onChanged { value in
        self.location = value.location
      }
      .onEnded {_ in }
  }

  var body: some View {
    ScrollView(.horizontal) {
      HStack {
        ForEach(colors, id: \.self) { color in
          Group {
            if color == .green {
              VStack {
                color
                  .frame(width:100, height: 100)
                  .position(location)
                  .simultaneousGesture(simpleDrag)
              }
            } else {
              color
            }
          }
          .frame(width: 200, height: 200)
        }
      }
    }
    .frame(width: 400, height: 400)
  }
}

I've been searching for a similar answer as well. The closest I could find to a solution is to set the minimumDistance parameter of DragGesture. I found that DragGesture(minimumDistance:20) works fairly well to allow the TabView paging to happen before the DragGesture kicks in. It does delay the other gesture by 20 pixels, but it seems like a fair compromise to allow for both kind of gestures to function

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM