You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI中Section内嵌VStack时拖拽子元素触发整体拖拽如何解决

问题根因

Form 本质是基于 List 封装的布局容器,默认会把 Section 下的每个直接子视图识别为单个列表行,列表行自带的全局交互手势优先级高于内部子视图的自定义手势,所以你拖拽 VStack 内部元素时会触发整个VStack/Section的拖拽行为。

解决方案

只需要给嵌套的VStack添加修饰符,清除掉默认的列表行属性,同时给子元素指定明确的交互响应区域即可,修改后的代码如下:

enum TestData: String, CaseIterable {
  case one, two, three
}

struct ContentView: View {
  var body: some View {
    Form {
      Section {
        VStack(spacing: 12) { // 可自行调整子元素间距
          ForEach(TestData.allCases.reversed(), id:\.self) { text in
            Text(text.rawValue)
                .frame(maxWidth: .infinity, alignment: .leading) // 撑满可用宽度,方便拖拽操作
                .contentShape(Rectangle()) // 指定交互响应的精确区域
                .onDrag {
                    NSItemProvider(object: text.rawValue as NSString)
                }
          }
        }
        .listRowInsets(EdgeInsets()) // 移除系统默认的列表行内边距
        .listRowBackground(Color.clear) // 移除系统默认的列表行背景样式
      }

      Section {
        ForEach(TestData.allCases, id:\.self) { text in
          Text(text.rawValue)
          .onDrag {
            NSItemProvider(object: text.rawValue as NSString)
          }
        }
      }
    }
  }
}

如果需要保留VStack默认的列表行卡片样式,也可以给每个子元素添加长按手势抢占响应优先级,在onDrag前添加以下修饰符即可:

.onLongPressGesture(minimumDuration: 0.2) {}

内容的提问来源于stack exchange,提问作者Phantom59

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 19:45:02