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

SwiftUI技术问询:如何在不拖动Sheet到顶部时滚动其内的List

解决Sheet内List滚动与Sheet拖动冲突的问题

要实现像Instagram评论区那样,直接滚动Sheet内的List而不会先触发Sheet拖动到顶部的行为,你可以通过以下两种方案解决手势冲突问题:

方案一:仅允许顶部区域拖动Sheet(推荐,贴近Instagram交互逻辑)

这种方式将Sheet的拖动权限限制在顶部的SomeView区域,List区域直接响应滚动,不会触发Sheet拖动:

  1. 隐藏默认的Sheet拖动指示器
  2. 给顶部的SomeView添加自定义拖动手势,用来控制Sheet尺寸

修改后的代码如下:

struct CustomSheetView: View {
    @Binding var currentDetent: PresentationDetent
    
    var body: some View {
        VStack {
            // 仅顶部区域可拖动调整Sheet
            SomeView()
                .gesture(
                    DragGesture()
                        .onChanged { value in
                            let translationY = value.translation.height
                            // 根据拖动距离切换Sheet尺寸
                            if translationY > 50 {
                                currentDetent = .fraction(0.8)
                            } else if translationY < -50 {
                                currentDetent = .large
                            }
                        }
                )
            
            Spacer()
            
            List {
                ForEach(1...40, id: \.self) { index in
                    Text("Item \(index)")
                }
            }
            
            Spacer()
            
            SomeOtherView()
        }
    }
}

struct ContentView: View {
    @State private var isSheetVisible = false
    @State private var currentDetent: PresentationDetent = .fraction(0.8)
    
    var body: some View {
        Button("Open Sheet") {
            isSheetVisible = true
        }
        .sheet(isPresented: $isSheetVisible) {
            CustomSheetView(currentDetent: $currentDetent)
                .presentationDetents([.fraction(0.8), .large], selection: $currentDetent)
                .presentationDragIndicator(.hidden) // 隐藏默认拖动指示器
        }
    }
}

方案二:让List滚动手势优先响应

通过给List添加高优先级手势,强制List的滚动手势优先于Sheet的拖动手势,在List区域滚动时直接触发List滚动:

修改CustomSheetView中的List部分:

List {
    ForEach(1...40, id: \.self) { index in
        Text("Item \(index)")
    }
}
.highPriorityGesture(
    DragGesture(minimumDistance: 0)
        .onChanged { _ in } // 空实现,仅用于抢占手势优先级
)

这种方式实现更简单,但会导致整个List区域无法拖动Sheet,适合不需要保留Sheet全局拖动功能的场景。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 06:43:16